How to structure a frontend design system
Four layers, one rule about which may reach which, and why that rule is the whole system.
UT Studio7 min read
A design system is not a component library. A component library is a folder of components; a design system is a set of constraints that makes new components consistent with old ones without anybody remembering to make them so.
Four layers
Tokens
└─▶ Primitives Button, Field, Card, Alert
└─▶ Patterns Form, Table, Navigation
└─▶ Compositions Page sections, full screensThe rule
**Each layer may only reach the layer directly beneath it.** That single constraint is what makes the whole thing hold.
A primitive reads tokens and nothing else. A pattern composes primitives. A composition arranges patterns. When a composition reaches past patterns and primitives to hard-code a colour, that colour is now outside the system — and it is the one that stays wrong after a rebrand, in a footer nobody looks at.
Tokens: name the meaning, not the value
| Instead of | Name it | Because |
|---|---|---|
| --blue-500 | --color-primary | The brand changes; the role does not |
| --gray-100 | --color-surface-sunken | Says where it is used |
| --size-12 | --space-md | Rescales without renaming |
The test for a token name
If a rebrand would make the name a lie, it is named after its value. `--color-danger` survives; `--color-red` does not.
Primitives: as few props as will do
A primitive with fifteen props is a small application. Each prop should map to a design decision that genuinely varies — `variant`, `size`, `tone` — and never to a one-off need.
A className escape hatch will become the API
Allow arbitrary class overrides and within a quarter every call site has its own tweaks and the system describes nothing. Either the variant exists or the design should change.
Prove it composes
The only convincing evidence that a design system works is a complete product built from it — not a documentation site with a grid of buttons. If level four cannot be assembled from level one, the layers are decorative.
Document as you build
- Every primitive: what it is for, and what it is not for.
- Every token: its role, not its value.
- Every pattern: the composition it expects.
- A changelog, because a design system without one cannot be upgraded safely.
Systems you can read
Foundry publishes all four layers, including complete starter products assembled from its own primitives.
Templates mentioned here
Everything above is written against real products. These are the ones this page draws on.
