Design systems that actually ship
Most design systems stall in Figma. The ones that survive contact with production share a few unglamorous habits.

In this article
A design system is one of the easiest things in software to start and one of the hardest to keep alive. Most of them end up as a gorgeous Figma library with three hundred variants, a tidy colour ramp, and almost nothing in production that matches it. The distance between that file and the running app is where the whole effort quietly dies.
01Treat the system as a product with users
The teams that keep a system alive stop treating it as a deliverable and start treating it as a product. A product has users, and here the users are engineers. If a developer finds it faster to copy a div and hand-tune the padding than to reach for your component, you have lost that engineer, and a better wiki will not win them back. So you optimise for the unglamorous moment: a developer mid-feature, slightly behind on an estimate, deciding in two seconds whether to trust your button or roll their own.
No volume of documentation will make an engineer reach for a component that is slower than rolling their own.
02Let code and tokens be the single source of truth
Almost every stalled system I have seen ran on two sources of truth: a Figma file the designers trusted and a codebase the engineers trusted, drifting a little further apart with every sprint. You cannot keep two canonical copies of anything in sync by hand for long. One of them has to win, and in production it has to be the code. Design tokens are how you make peace between the two: define colour, spacing, type and radius once as named values, generate the platform outputs from that single source, and let both Figma and code consume it. When a designer changes the brand blue, it should reach the app through a pull request, not a Slack message asking someone to remember to update a hex code.
03Start with the components you already ship
The instinct is to design the entire kit before anyone uses a single piece of it. Resist it. Open your real product, count how often each component actually appears, and you will almost always find that a button, an input, a select, a modal and a handful of type styles cover the bulk of the surface. Build those, ship them into one genuine screen, and widen the net only once they have held up under real traffic.
A small system running in production earns more than a comprehensive one still sitting in review, and the payoff compounds over time:
- Engineers adopt what is in front of them, not what is promised on a roadmap
- Every component you ship is one you now maintain, so fewer is genuinely cheaper
- Real usage surfaces the variants you actually need and quietly kills the ones you imagined
- A working core earns the credibility to fund the rest of the work
04Make contribution easier than the workaround
Governance sounds like a committee and a long document. In practice it reduces to one question: when an engineer needs a component that does not exist yet, what happens next? If the answer is a request that vanishes into a backlog, they will build their own version locally, and your system will quietly fork a hundred times in private. If the answer is a short, clear path to contribute, the system grows with the product instead of against it. Write down how a change is proposed, who reviews it, and what done means, then keep the whole process light enough that people follow it rather than route around it.
A design system grows at exactly the rate that contributing to it is easier than working around it.
05Version, deprecate, and measure what people use
Treat the system as the dependency it is. That means semantic versioning, a changelog written for humans rather than machines, and a deprecation path that gives teams a release or two to migrate instead of breaking them on a Tuesday morning. It also means resisting the urge to design every edge case in advance. Ship the common case, version it honestly, and let the rare states arrive when a real screen actually demands one. A system you can evolve safely is worth far more than one that is complete and frozen.
You also have to know whether any of it is working, which means measuring adoption rather than assuming it:
- The share of the UI built from system components versus bespoke one-offs
- How many teams are on the current major version versus stranded on old ones
- The time from a token change to it landing in production
- The number of local overrides, which points straight at where the system is failing people
None of this is glamorous. Nobody adds a deprecation policy or a contribution guide to their portfolio. But these are the habits that separate a system people build on from a beautiful file nobody opens. The pretty part was never the hard part. Staying useful, release after release, is the actual work, and it is the only thing that tells you whether you built a design system or just a very tidy archive of good intentions.
Key takeaways
- A design system survives only when engineers find it faster to use than to work around, so treat it as a product whose users are the people writing the code.
- Keep one source of truth in code, drive it with design tokens, and start with the handful of components your product already ships instead of designing the whole kit up front.
- Make contributing easier than building a local workaround, version the system like the dependency it is, and give teams a real deprecation path rather than breaking them without warning.
- Measure adoption directly through the share of UI built from the system and the number of local overrides, because a system you cannot evolve safely is worth less than one that is merely complete.
Keep reading
More insights.
Have a project in mind? Let's talk.
Tell us where you want to go. We'll map the shortest credible path.



