Design Systems That Actually Ship: Avoiding the Documentation Graveyard
How Design Systems End Up in the Graveyard
Many design systems start the same way: a big Figma library, a documentation site and a launch announcement. Six months later the Figma file says one thing, the production code says another, and the documentation site describes a version of the product that no longer exists.
The problem is rarely effort. It is that the system lives somewhere other than the product. Every change has to be made twice, once in design and once in code, and the documentation is a third copy that nobody is responsible for. Copies drift, and once people notice the drift they stop trusting the system and start working around it.
A design system that ships is not a 200-page Figma file. It is the living contract between design intent and production code, and the only way to keep a contract honest is to keep one copy of it.
The Token-First Architecture
Design tokens are the named decisions underneath everything else: colours, type scale, spacing, corner radii, shadows and motion timings. Define them once, in code, and have everything else read from them.
With Tailwind CSS v4, tokens can be declared as CSS custom properties in a single @theme block, and every utility class and component picks them up from there. With plain CSS, custom properties on the root element do the same job.
When designers and developers use the same names, such as accent, surface and display, there is no translation step between a design file and a pull request. Changing a brand colour becomes a one-line change, not a search through hundreds of files.
Name tokens by purpose, not by value. A token called surface still makes sense after a rebrand. A token called grey-900 does not.
Components Are the Documentation
Tokens keep the details consistent. Components keep the patterns consistent: buttons, form fields, cards, dialogs and navigation, each built once with accessibility and edge cases handled, and reused everywhere.
The most reliable documentation for a component is the component itself: typed props that say what it accepts, sensible defaults, and live examples rendered from the real production code rather than screenshots. Documentation generated from the code cannot fall out of date.
Build components in the product, for a real screen that needs them, and extract them once a second or third screen needs the same thing. Components designed in isolation for hypothetical future use tend to be either too rigid or too flexible to be useful.
Shared Components Make Big Changes Possible
The payoff shows up during large changes. From 2020 to 2021, while at Kablamo, I worked on Jira’s issue and board views as they moved from a legacy monolith to a new React and Redux front end, migrating features one by one without breaking what customers relied on.
Migrations like that depend on shared building blocks and conventions that every team can rely on. Without them, each migrated feature rebuilds the same pieces slightly differently, and the new codebase starts collecting the inconsistency the migration was meant to remove.
Keeping the System Alive
• Make the right thing the easy thing. If using a token is quicker than typing a hex value, people will use the token.
• Enforce with tooling, not reminders. Lint rules, type checks and visual regression tests catch drift in code review rather than months later.
• Give the system an owner, even part-time. Someone has to decide what gets added, what gets deprecated and when.
• Deprecate in the open. Mark old components as deprecated, point to the replacement, and remove them on a published schedule.
• Start small. A handful of tokens and five well-built components used everywhere beat a hundred components used nowhere.
Looking to elevate your digital presence?
We partner with a limited roster of ambitious brands each quarter. Discuss your vision directly with our design leadership.