Design systemsField notes
The second system
Six rules for design systems that we only learned by breaking them.
Most articles about design systems are written at launch. They describe the token architecture, the component library and the governance model before any of it has met a second team. This is the other article: ours had met its tenth team, outgrown its first architecture, and been handed a budget to start again.
Fred Brooks warned in 1975 that the second system is the dangerous one. It is where every idea that lost the first design review gets a second chance, along with everything its architects have admired since (usually, they deserve a second rejection). We proved him right for about eight months. Then we started deleting.
Here are six things we believed about design systems, and what replaced each belief. None is about a framework. Each took us months to learn, and the whole list takes seven minutes to read, which is about the best deal a blog post can offer.
01Releases
Nobody upgrades
Here is a chart design-system teams rarely publish. We scanned every active frontend that depends directly on our first generation. Twenty apps declared nine different versions. The largest group, eight apps, sits on the same patch release.
Nobody did anything wrong. A team installs whatever is current, pins it and gets back to its own roadmap. Upgrading a dependency that works is a cost with no visible feature attached, so it loses every prioritisation meeting it walks into.
Every release you ship is a version someone will live in for years.
If you never say how long you support a version, the answer defaults to forever. Software is very good at turning silence into policy. So the rewrite publishes its support window before its first stable release. Removals happen only in a major version, with a migration path attached.
02Tokens
Procrastinate on every knob
We started the rewrite with a token for every property of every component, so a brand could restyle anything without touching the system. Nobody had asked for any of them. The design systems we admired had that tier, so we copied it. Eight months later, we deleted it.
A knob looks free on the day you add it. The invoice arrives when somebody uses it.
From then on it is part of your contract, with documentation, a lint rule and a migration path to maintain, and it does things you never planned for. Our padding token let any team make its buttons tighter in one line of CSS nobody would review. It turned out to be a knob for the rhythm that makes two products feel like one.
So we procrastinate on purpose. A knob waits until a team brings a real use case, and even then it has to answer two questions. What might teams do with it that we can’t foresee? And what will it cost us when we want to change the thing it controls? Teams that can’t wait still have a way out: plain CSS, where everyone can see it.
Stepping outside the system should look like stepping outside the system.
03Theming
A brand is not a colour
Several brands share this system, and we saw the conflict coming before the first theme existed. Our brands are red, orange and blue. In our interfaces, those colours already have jobs. Red and orange mean something is wrong, and blue means selected.
Brand marketing wanted more brand colour in the apps, and from where they stood, that was the right instinct. On a website, colour is how you recognise a brand, and more of it usually helps. In an application people work in all day, colour is how the screen tells you what needs attention. It is never the only signal, but it is the fastest one, and every decorative use of red makes the next error easier to miss. Keep going, and everything is on-brand, including the things users need to worry about.
On a marketing site, colour is identity. In an application, colour is information.
So in our applications, multibrand means less than a brand guide might suggest. A theme may change the character of a colour (warmer, cooler, more or less vivid) as long as text on it stays readable, and it never changes its role. A brand can bring its own blue, and blue still means selected. A theme may also swap the typeface and add the logo. That is the whole list, for now. Every product is recognisably its brand, and an error looks like an error in all of them.
04API design
One component, one role
The single responsibility principle applies to components with unusual force. A component is a contract: one purpose, an API that serves it, and behaviour consumers can rely on. Nobody designs a component to serve two purposes. It happens one reasonable request at a time: a team needs something close to an existing component, stretching it feels cheaper than adding another, and one day it quietly holds two contracts.
That is the smell, and the code hides it. Code grows by addition. Complexity grows by multiplication. Every extra purpose meets every concern the component already has, from rendering and styling to keyboard behaviour, accessibility and documentation, until every part of the component is a question with two answers. The API becomes the union of both, no reference page can say which half applies when, and the bugs live in the combinations nobody thought about. Eventually, a one-line fix for one use needs a migration guide for the other, three approvals and a meeting to work out which contract the bug was in.
More code is fine. More complexity is not.
A second component costs a few lines of proven boilerplate: more code, but nothing new to think about. The two can share a base and their styles, and each still does one thing. If you can’t say what a component is for without an “or”, it is probably two components.
05Interaction
Keys are design tokens too
Colour has tokens. Spacing has tokens. Keyboard behaviour usually lives in a switch statement inside each component, and ours did too. Everyone knows that Escape closes things: a dialog, a dropdown, a tooltip, a side panel. In our first generation that was four implementations written by four people, and one of them had forgotten. The only thing keeping Escape meaning “close” across the system was a careful reviewer. This was less an architecture than a superstition with code review.
So we gave keys the token treatment. One vocabulary file is the only place in the code allowed to mention a key. It maps keys to meanings such as activate, dismiss and move down, and components ask for meanings. A new shortcut is a proposal to the vocabulary, reviewed the way you would review a new colour, and the keyboard tables in the docs are generated from the meanings each component declares, so they can’t drift.
The surprise was who owns the file. Keyboard behaviour had always been treated as an engineering detail. Once it was a vocabulary, it was obviously a design decision, and design now owns it.
06Architecture
Taste needs a default
Atomic design sorts components into atoms, molecules and organisms. It’s a good teaching model and a poor rule for deciding what may depend on what. “Is this a molecule?” is a judgement, and every person who reads the rule makes it again. Ten readers, ten slightly different systems. At that point the taxonomy is a personality test.
The deeper problem is that the answer depends on the author, not the component. A combobox can be assembled from an input, a popover and a list of options. An option can be assembled from a checkbox and a label. Build them that way and they are molecules. Build each one as a self-contained component and they are atoms. Same pixels, a different system underneath.
The molecule version has a cost the taxonomy doesn’t price in. Every component that uses another component is coupled to it. Change the checkbox, and the option, the combobox and every list of options change with it. Basic elements that depend on each other make a design system rigid: nothing small can move without moving everything above it.
Share behaviour, not components.
So our default is the atom. Behaviour that several components need, such as styling patterns, keyboard handling and positioning, lives in utilities any component can use. A component depends on another component only when it really can’t do its job alone, and whoever wants that dependency has to argue for it.
That is still taste, and it always will be. You can’t take taste out of a design system, and you shouldn’t try. What you can do is give it a default and put the burden of proof on the exception. A taxonomy needs everyone to judge the same way. A default only needs someone to object.
PSRecords
Keep the superseded records
None of this was written from memory. It came from decision records, and nearly all the useful ones had been superseded by a later record. A superseded record shows what we believed, what changed our minds, and when. The code only shows where we ended up.
If you start a design system tomorrow, start the records in the first week and keep them next to the code. Let them be wrong. When one is superseded, link the old record to the new one. A year later, you’ll have something rarer than documentation: a written history of how your thinking changed.
Based on the architecture and design decision records of one design system, 2025–2026. Version figures come from a scan of the organisation’s repositories in September 2026, counting frontends with a commit in the previous twelve months.