Your design system is an npm package
Most design systems do not fail at the design stage. They fail at the distribution stage. The components are thoughtful, the Figma library is immaculate, the documentation site is genuinely nice — and six months later three products have three different buttons, because nothing ever forced them to converge.
A design system is not a document. It is a dependency. Until it installs, versions and breaks like one, it is a strong suggestion.
Tokens are the contract
The base layer is not components, it is decisions: colour, type scale, spacing, radii, motion. Those live once, in a machine-readable form, and everything else derives from them. Change a token and every surface that consumed it changes with it — which is the point.
/* One source of truth. Themes redefine, never redeclare. */ :root { --space-3: 12px; --radius-pill: 100px; --accent: #3f6dff; --ease: cubic-bezier(.22, 1, .36, 1); } [data-theme="dark"] { --accent: #5b8dff; /* same role, different value */ }
The discipline that keeps this honest is refusing raw values in product code. A hex code in a feature branch is a token that has not been named yet, and a linter can say so before review does.
Semver is how you keep trust
Publish the system as a package with real version numbers and the relationship changes. Consumers upgrade deliberately. A breaking change announces itself as a major bump rather than as a support ticket about spacing. Teams that need to move slowly can, without blocking the ones that want the latest.
A design system nobody can upgrade safely is a design system nobody upgrades.
It also forces a useful conversation about what "breaking" means for UI. Renaming a prop is obvious. Changing a default shadow is not, and reasonable people disagree — so write the policy down once and follow it, rather than relitigating per release.
Storybook is the test suite, not the brochure
Every component ships with its states enumerated: empty, loading, error, long string, right-to-left, disabled, focused. That catalogue is worth more as a test target than as documentation. We run accessibility checks and visual diffs across those stories in CI, so a padding change that quietly wrecks the disabled state fails the build instead of shipping.
- Accessibility in CI: keyboard path, roles and contrast checked per story, as part of the same WCAG 2.2 AA commitment we hold the rest of the work to.
- Visual diffs: pixel changes surface as a reviewable artefact.
- Type-safe props: the API is enforced by the compiler, so misuse is a build error and not a bug report.
- One publish path: tagged release, CI builds, registry gets it. No laptops involved.
The part that actually decides it
Adoption is not a technical problem, but technical choices make it much easier or much harder. Systems get adopted when using them is the path of least resistance: when the component is easier to install than to reimplement, when the migration comes with a codemod rather than a spreadsheet, and when someone owns the thing well enough to answer a question the same day.
Get that right and the system compounds. Every product built on it starts further along, and consistency stops being something you police.
Start here
Let's build the thing they can't stop using.
Send the brief. A senior engineer reads every one and comes back with an architecture, a plan and a quote written against your actual scope — usually within a day.