01 / 07 · Case studySaaS
One design system shared across three products.
One system for three products
I built the design system behind Sciene’s Companion: the tokens, the component library, the accessibility standards and the documentation. Engineering built it in React and Tailwind. I didn’t write the production code, but I reviewed the implementation with them until design and code matched.
- 3× faster to ship a feature, comparing delivery time before and after the system
- 100% token parity between Figma and code
- 50+ components shared across three products
- 0 screens redesigned to ship the v2 Director Dashboard

Three products, three versions of everything
Account Flagging, the Email Hub and the Meeting Hub each solved the same button, status and layout on their own. On top of legacy code, that meant slower builds, inconsistent screens and a steady stream of bugs.

- Two button languages in one toolbar. An outline action next to a filled one, neither clearly primary.
- The active nav item is a solid blue bar, while other rows change text colour only on hover.
- A third blue, in a third shape, for the company badge.
- Every metric card carries its own border and padding, set per screen rather than from a shared card.
Built alongside v1, not before it
Engineering was already shipping, so the system couldn’t pause the product. I built it alongside v1 and adjusted components as we delivered.
- FoundationsColour ramp, type scale, spacing steps, radii. Decided once, argued about once.
- Semantic tokensRoles rather than values.
btn-primary-bg,btn-secondary-bg,bg-secondary, and the severity roles behind critical, warning, and healthy. - PrimitivesButton, input, select, checkbox, badge. No product knowledge in them at all.
- ComponentsThe alert row, the filter bar, the metric card. Primitives composed into things that know a little about the domain.
- PatternsTriage list, acknowledgement flow, empty and loading behaviour. The rules for how components sit together.
- ProductAccount Flagging, the AI Email Hub, the Meeting Hub. Assembled from the layers above, holding only what is genuinely specific to them.
- Raw value#f2f4f7
- Semantic role
btn-secondary-bg - PrimitiveSecondary button
- ProductSnooze, on an alert a CSM is triaging
Foundations every component inherits
Components never pick a raw value. Colour, type, radius and elevation are tokens: primitives first, then semantic names on top, so changing one updates all three products.
Brand
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
Neutral
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
Severity, as semantic tokens
- Critical
fg-errorbg-error-primary - Warning
fg-warningbg-warning-primary - Healthy
fg-successbg-success-primary
Severity is decided once, in the tokens
Critical, warning and healthy appear in all three modules. I rejected per-product palettes, because the same red has to mean the same thing in the Email Hub as in Account Flagging. Each severity became a token with a fixed colour, icon and weight. Severity never relies on colour alone.
- Token
severity.critical- Colour
error- Icon
octagon-alert- Weight
500
Critical. Colour error, icon octagon-alert, weight 500
Secondary buttons fill, and so does hover
Outline buttons disappeared next to dense tables and read as decoration. I replaced them with filled secondary buttons, and made every hover a fill instead of a colour change, which is easy to miss while scanning forty accounts.
| Account | Open flags | Last contact | Action |
|---|---|---|---|
| Coastline Pet | 2 | Today | |
| Harbor & Pine Home | 3 | Yesterday | |
| Juniper Kitchen | 1 | 3 days ago | |
| Atlas Trail Gear | 0 | Last week |
Docs written for engineers and their AI assistants
Figma-only notes left engineers guessing. I wrote the docs as usage rules with semantic token names, so a person or an assistant asking for an alert row picks the right component. Consistent AI output took iteration: I built skills that encode the rules and kept refining them until the output held.
severity.critical
- Meaning
- An account needs action today
- Use for
- Alerts that block revenue or renewal
- Don’t use for
- Errors in a form; use the field error state
- Pairs with
- Alert icon, text label
Produces
CriticalThe Director Dashboard came from parts we already had
By v2, someone could build a screen I’d never drawn and it still looked like Companion. The Director Dashboard shipped without a single new screen designed from scratch.
What I’d change
I componentized too early. Things that looked like patterns after two uses turned out to be coincidences, and I folded several back into their screens. Now I wait for the third use before promoting anything.
