Tokens that survive contact with developers
The usual first attempt at tokens is a palette named after the colours. Brand blue, light blue, grey ninety. It works until somebody needs to know which grey is for borders and which is for disabled text, and then it becomes a matter of taste again. Naming by appearance also makes a dark theme almost impossible, because a token called light grey cannot sensibly become dark grey without every reference in the codebase reading as a lie.
Two layers solve it. Primitive tokens hold the raw values and are never used directly. Semantic tokens name a purpose: surface, surface raised, text primary, text muted, border subtle, action, action hover, danger. Components reference only the semantic layer. Changing a theme then becomes a remapping of that layer, and a developer choosing a colour is choosing a role rather than a shade, which is a decision they can make correctly without consulting anybody.
For this to hold, the tokens need one source that generates both the design tool variables and the code artefacts, whether that is a stylesheet with custom properties, a theme file or platform specific output. When designers and developers maintain separate copies, the two drift within a release or two, and the drift is invisible until somebody compares screens side by side. A generated pipeline is not sophisticated engineering. It is the difference between a system and a suggestion.
- A primitive layer of raw values that components never reference directly
- A semantic layer naming purpose, such as surface, text muted, border subtle and danger
- One source generating both design tool variables and the code artefacts developers consume
- Theming handled by remapping the semantic layer rather than by editing components
- Spacing, radius and type held on a scale, so arbitrary values stand out in review