How to Build a Design Token System from Scratch
Step-by-step guide to building a design token system: naming conventions, token tiers, CSS variable output, and Figma integration for product teams.
Your engineers are hardcoding #1A73E8 directly into components. Your designers are copying hex values from a shared doc that nobody updates. Every theme change requires a global find-and-replace that still misses something. The root cause is the same: you do not have a token system.
What Is a Design Token System
Design tokens are named variables that store a single design decision: a color, a spacing value, a typeface, a shadow. The token color.brand.primary carries the value #1A73E8. When that value changes, you update one place and every component that references the token inherits the change.
A design token system is the architecture governing how tokens are named, tiered, output to different platforms, and connected between design tools and code.
The Three-Tier Token Model
The most durable token architectures use three tiers: primitive, semantic, and component.
Tier 1: Primitive tokens
Primitive tokens are raw values with no context attached.
color.palette.blue.500 = #1A73E8
color.palette.blue.600 = #1557B0
spacing.4 = 16px
font.size.base = 16px
These are your full palette. They never appear directly in component code.
Tier 2: Semantic tokens
Semantic tokens alias into primitives and carry intent. They describe roles, not values.
color.action.primary = color.palette.blue.500
color.action.primary-hover = color.palette.blue.600
color.text.default = color.palette.neutral.900
spacing.component.padding-sm = spacing.4
This tier is what your component library consumes. It is also what you swap when switching themes or color modes.
Tier 3: Component tokens
Component tokens alias into semantic tokens and describe decisions scoped to one component.
button.background.default = color.action.primary
button.background.hover = color.action.primary-hover
button.padding-x = spacing.component.padding-sm
Not every team needs tier three. Add it when multiple components share semantic tokens but diverge in ways that semantic tokens cannot express cleanly.
How to Build a Design Token System Step by Step
1. Audit what exists
Before naming a single token, list every raw value currently hardcoded in your codebase or design files. Group by category: colors, spacing, type, shadows, border radii, durations. You will find duplicates, near-duplicates, and values that belong to no obvious system.
2. Define your primitives
Create a complete palette for each category. For color, generate a full scale (50 through 900 for each hue). For spacing, use a base unit (typically 4px or 8px) and define multiples: spacing.1 = 4px, spacing.2 = 8px, and so on up to your maximum. For type, define a scale based on a consistent ratio.
3. Name tokens for humans, not machines
Token names must be readable by both designers and engineers. Use dot notation or kebab-case consistently. Be descriptive at the semantic layer:
- Good:
color.feedback.error,color.text.disabled - Avoid:
color.red,color.gray3
The first set communicates usage. The second communicates nothing beyond the raw value.
4. Output tokens to each platform
Tokens live in a format-agnostic source — typically JSON or YAML — and are transformed into platform-specific outputs using a tool like Style Dictionary.
For web: CSS custom properties or JavaScript objects. For iOS: Swift color definitions. For Android: XML color resources.
CSS output from color.action.primary:
:root {
--color-action-primary: #1a73e8;
}5. Connect Figma to your token source
Use a plugin like Tokens Studio (formerly Figma Tokens) to sync your token source with Figma variables. This closes the gap between design and code: when a token changes in the source, designers and engineers see the same value.
6. Implement dark mode through semantic tokens only
Dark mode is not a different palette. It is a different mapping of semantic tokens to primitives.
/* Light */
color.surface.default = color.palette.neutral.50
/* Dark */
color.surface.default = color.palette.neutral.900
Swap at the semantic layer. Your component code never changes.
Common Mistakes to Avoid
- Skipping the primitive tier and aliasing semantic tokens directly to hex values. Now theme changes require editing every semantic token.
- Naming by value rather than role.
color.bluebreaks the moment your brand changes or a dark theme inverts the meaning. - Defining tokens in design tools but not in code. The source of truth must be a version-controlled file, not a Figma library.
- Ignoring accessibility metadata. Document which color tokens meet WCAG contrast thresholds and for what background. That information belongs in the token spec.
Maintaining the Token System Over Time
Every token is a commitment. Before adding one, ask whether the need is specific enough to require its own variable or whether an existing semantic token covers it. Token sprawl is a real failure mode — systems with hundreds of overlapping semantic tokens become impossible to navigate.
Assign a single owner to the token layer. Run token changes through a review process that includes at least one designer and one engineer. Treat the token source file as a core dependency with a changelog.
A well-built design token system is the first investment that pays dividends across every subsequent component you build. Get the foundation right and theming, dark mode, rebranding, and multi-product consistency become configuration changes rather than engineering projects.
Clixo builds design token systems that span multiple products and platforms.