CleverX · design system
Sixty pages,
four engineers,
one system.
Building a product's first design system when the product already exists, the engineers already have opinions, and nobody has ever opened Figma.
Colour, type, and the components that carry them: the whole system on one sheet. Everything below is the argument for why each of these looks the way it does.
None of that existed when I arrived. Every page had been built by whoever needed that page: the same button drawn five slightly different ways, four purples that were nearly but never the same purple, padding chosen fresh each time. This is what a product looks like when it works and nobody owns how it looks.
01 · the starting point
Why nobody had fixed it
The engineers had shipped a working product without a designer. That's not a failure. It's the reason the inconsistency existed. Every page was built by whoever needed it, making reasonable local decisions with nothing global to defer to.
Which meant the system couldn't arrive as a rulebook. Four people had been making these calls for years and were about to be told to stop. It had to be worth adopting, not just correct.
02 · foundation
Brand before buttons
We didn't start by drawing buttons. We ran a brand exercise as a team first, covering vision, mission and values, then chose colours for what they'd communicate rather than what looked current. We checked contrast while picking them, with plugins in Figma, because a palette that fails is a palette you rebuild.
It sounds like a detour. It meant that when someone asked why is the primary violet, there was an answer that wasn't "because I liked it." Every argument about colour after that was short.
One of those values, that the product should recede and stay out of the way of the work, is the one that later decided how few colours the system could spend.
03 · sequencing
Three phases, by blast radius
Colour, type, buttons.
These touch every page in the product, so standardising them first bought the widest reach for the least work.
Inputs, cards, modals, badges, navigation.
The building blocks of study creation, dashboards, and participant management: the pages people actually lived in.
Everything else, as the product asked for it.
New feature, new component, added to the system rather than built beside it.
The cost was real and I'd take it again: features slipped by days, and in one case by weeks, because we were rewriting production pages onto the new system instead of building what was on the roadmap. Sequencing by blast radius also means the loudest inconsistencies stay visible the longest. You fix the invisible foundation first, and for two months it doesn't look like you've done anything.
04 · the rules
Components are easy. Rules are the work.
Drawing a button is an afternoon. Deciding what it means, where it goes, and who is allowed to use it is the part that every future page inherits, so getting it wrong compounds across sixty of them.
Every combination drawn, not inferred. A state you didn't draw is a state an engineer invents.
Two styles for the same five statuses: a tint with coloured text, and a solid with light text. Four colours carry a meaning and grey carries none.
Five states across every field type. Focus is blue because it is a system signal, not a brand one.
06 · the breaking change
The modal we had to split
Modals appeared on nearly every page, and we shipped them as one component. That held until the product started needing modals to do different jobs.
Deleting a study isn't the same interruption as confirming one, which isn't the same as reading a notice, which isn't the same as filling in a form. One component was quietly doing four jobs with four button configurations and four tones, and getting all four slightly wrong.
Modal or dialog? If the user has to do something, it's a modal. If they only need to know something without leaving the dashboard, it's a dialog.
There was no versioning and no migration path. What there was instead: we iterated until the rules held, then sat with the dev team and walked through the reasoning for each split, not the redlines, the why. They updated their components once, and it propagated everywhere in the code.
The honest read is that we shipped the modal before the product had told us what states it needed. Building the general case first felt efficient and wasn't.
07 · adoption
Getting four engineers to use it
The engineers built their own component library in code, mirrored from the Figma system. That was the adoption mechanism and I didn't design it. They did, because they needed something they could import. When the system changed we told them what changed and why, they updated their components, and it landed across the product.
It worked because the sync was human. It was fragile for the same reason.
The place it broke was button text. In Figma the button was the right height; in production it wasn't, because line-height resolved differently in the browser than in the design file. A small bug, except buttons are on every page, so the system's most-used component was visibly wrong everywhere while the Figma file insisted it was fine.
Same button, same label. The only difference is whether line-height was left to inherit.
That was the moment the system stopped being a Figma file to me. If what engineers ship doesn't match what I drew, the drawing isn't the system. Theirs is.
08 · accessibility
Checked while choosing, not audited after
Contrast was checked during palette selection rather than afterwards, which is the only order that works. A palette that fails is a palette you rebuild. Focus states were part of every interactive component's state set from the start, alongside hover and pressed, rather than added when someone asked. Keyboard access was built in.
None of this was heroic. It was cheaper than the alternative, which is finding out at launch.
09 · what changed