Every design system starts with tokens, and most of them go subtly wrong in a way that only hurts about eighteen months later — usually the exact day someone asks for dark mode, or a rebrand, or 'can we have this on Android too?'. The failure is always the same one: tokens that describe what things look like instead of what they're for.
01 Name the role, not the value
blue-500 is a paint bucket. surface-raised is a decision. The first one is useless the day the brand changes; the second survives any redesign, because it stores intent instead of appearance. My rule: raw values — hex codes, pixel numbers — live in a base palette that nothing touches directly. Everything the product actually uses is semantic: ink, ink-dim, surface, accent, line.
This whole site runs on about a dozen semantic tokens. Dark and light theme? Same tokens, different values — the toggle is twenty lines, not a second stylesheet. When a component asks 'what colour is text?', the answer is always var(--ink). What --ink means is decided in exactly one place, and it's none of the component's business.
02 Layers, not aliases
Three layers. Base: raw values — the only place a hex code is legal. Semantic: role-named tokens that map to base. That's the public API. Component: rare, scoped overrides for the component that genuinely needs its own words. Aliases flow strictly downward. The moment a component reaches past semantic into base, you've signed a private contract that will break silently. On a Friday.
Keep the source of truth in one boring neutral file and generate the rest — CSS custom properties, TypeScript constants, native values. Generation feels like over-engineering right up until you change one value and watch it land in three frameworks at once. Then it feels like cheating.
03 It's a treaty, not a library
The architecture is the easy half. The hard half is people: tokens only work if using them is lazier than not using them. Lint against raw hex in components. Autocomplete the token names. Document the escape hatch for genuine exceptions, so nobody invents their own. A design system isn't a library — it's a treaty, and the tokens are its vocabulary.