Every company above a certain size eventually builds the same thing twice. Then three times. Then a team counts the button implementations scattered across its products and finds eleven, all slightly different, all maintained by someone who would rather be doing something else.
The usual answer is “let’s build a design system”, and the usual result is a component library: a package of buttons, inputs and modals with a version number. Six months later, half the products have adopted it, the other half have forked it, and the eleven buttons have become thirteen — two of them now live inside the design system.
I’ve spent the last decade on both sides of this problem — as a consultant delivering brand platforms, and now leading the cross-cutting frontends at Aruba. The lesson I keep re-learning is this: a design system is not a component library. It’s a decision-making structure that happens to ship code.
Components are the easy part
Writing a good button is a solved problem. What’s unsolved, in most organisations, is everything around it:
- Who decides when the button changes — the design system team, the product that needs the change, or the loudest voice in the room?
- Who pays for the migration when a breaking change lands — the team that broke it, or the twelve teams downstream?
- What happens when a product needs something the system doesn’t have — do they wait, fork, or contribute?
A component library answers none of these questions. A design system is these answers, plus the code that makes following them easier than not following them.
The economics of shared code
Shared frontend components have a property that makes them unlike most software: their value grows with adoption, but so does the cost of changing them. A button used by one product can change daily. The same button used by forty products is practically infrastructure — every change is a negotiation.
This is why “just extract the common components” fails as a strategy. Extraction creates the coupling without creating the governance. The teams that succeed treat the shared frontend as a product with users, not a codebase with consumers: it has a roadmap, intake, deprecation policies, and someone whose job is to say no.
That’s also why the role exists that I now hold — a product owner for the frontend platform itself. Not because components need a backlog, but because shared things need someone accountable for the trade-offs they impose on everyone else.
Three tests for a real design system
If you want to know whether you have a design system or a component library with ambitions, try these:
- The new-product test. Can a new product ship its first screen using only the system, in a day? If not, the system serves its authors, not its users.
- The breaking-change test. When the system ships a breaking change, is there a migration path that a downstream team can follow without talking to anyone? Governance you have to ask about is governance that doesn’t scale.
- The exception test. When a product legitimately needs to diverge, is there a sanctioned way to do it? Systems with no escape hatch don’t prevent divergence — they just stop hearing about it.
None of these tests mention visual consistency. Consistency is a side effect of a system that’s easier to use than to avoid. When you see an organisation with a beautiful Figma library and thirteen buttons in production, you’re not looking at a design problem. You’re looking at an ownership problem that nobody has written down yet.
The code is the easy part. Write down the decisions.