Exporting Design Tokens
Export is the moment a palette becomes code. The format matters less than the naming: tokens named after their role survive redesigns, tokens named after their colour become lies the first time the brand shifts.
Open the Color ConverterName by role, not by hue
`--color-primary` stays correct when the brand moves from blue to green; `--color-blue-500` becomes a trap that nobody dares rename. Reserve literal colour names for a raw scale, and layer semantic tokens on top of it.
Two layers work better than one
Keep a primitive layer (the raw ramp) and a semantic layer that points at it — `--surface: var(--grey-50)`. Theming then means repointing the semantic layer, and dark mode stops being a search-and-replace across components.
Choosing a format
CSS custom properties are the least friction for the web and support runtime theming. JSON is the right choice when tokens feed several platforms or a build step. A Tailwind theme extension is best when the project already lives in Tailwind and you want the colours as utility classes.
Step by step
- Settle the palette first — exporting an unfinished set just moves the churn into code.
- Decide the token names before exporting; renaming later is the expensive part.
- Export CSS variables for the web, JSON if other platforms consume them, or the Tailwind snippet for a Tailwind project.
- Paste primitives and semantic aliases in as two separate blocks.
- Replace hard-coded hex values in components with the token names.
Frequently asked questions
CSS variables or Tailwind config — which should I pick?
If the project uses Tailwind, extend the theme so colours arrive as utilities and stay in the design system. Otherwise use CSS custom properties: they need no build step and can be swapped at runtime for theming.
How many tokens should a small project have?
Fewer than instinct suggests. Six semantic roles plus a neutral ramp covers most interfaces. Add a token when a real decision needs a name, not in anticipation.
How do I handle dark mode?
Keep the semantic names identical and redefine them under a dark selector or media query. Components then need no knowledge of the theme, which is the entire point of the semantic layer.