Design Tokens Philosophy
A two-tier architecture that separates “what values exist” from “how values are used”—enabling scalable theming and consistent design decisions.
The Core Philosophy: Separation of Concerns
Our token system is built on a fundamental principle: separate raw values from their semantic purpose. This isn't just organizational tidiness—it's a governance strategy that enables theming, brand switching, and systematic evolution without breaking components.
When a designer specifies semantic.color.foreground.primary, they aren't picking a hex value. They're invoking a decision about hierarchy, contrast, and brand expression that has already been vetted. The token can be remapped to a different palette entry or tuned for light and dark modes, but its role and intent remain constant.
The Three Layers
Each layer represents a different level of abstraction, stability, and audience. Understanding where a token belongs helps teams make better decisions about naming, ownership, and extensibility.
Core Tokens
Raw values with no inherent meaning.
The core layer defines primitives—the building blocks. Color palettes, spacing scales, typography ramps, motion durations. These are intentionally meaningless in terms of UI purpose: core.color.palette.neutral.600 is just a gray—it doesn't say “use me for text” or “use me for borders.”
- Examples
core.color.palette.blue.500,core.spacing.size.04,core.typography.ramp.4- Stability
- Rarely changes; these are the physics of the system
- Audience
- System maintainers, token authors
Deep dive into Core vs Semantic
Semantic Tokens
Purpose and meaning assigned to primitives.
The semantic layer assigns roles by referencing core tokens. This is the theming surface—where brands diverge, accessibility constraints are enforced, and most designers interact with the system.
- Examples
semantic.color.foreground.primary,semantic.color.background.danger,semantic.spacing.gap.grid- Stability
- Names are stable; values change per theme/brand
- Audience
- Product designers, component authors
Deep dive into Multi-Brand Theming
Component Tokens
UI-specific composition of semantic roles.
The component layer applies tokens to anatomy—button backgrounds, card shadows, input borders. These alias back to semantic roles but give component teams a stable handle for customization.
- Examples
semantic.components.button.primary.background,semantic.components.input.border- Stability
- Tied to component API; changes with component evolution
- Audience
- Component developers, design system consumers
Deep dive into Build Outputs
Mode-Aware Tokens via Extensions
Rather than duplicating token files for light/dark themes, we use $extensions.design.paths to encode both variants in a single definition:
{
"foreground": {
"primary": {
"$type": "color",
"$value": "{core.color.mode.dark}",
"$extensions": {
"design.paths.light": "{core.color.mode.dark}",
"design.paths.dark": "{core.color.mode.light}"
}
}
}
}This says: “Primary text color references core.color.mode.dark in light mode, but flips to core.color.mode.light in dark mode.” The token definition stays in one place while encoding both theme variants.
The Reference Chain
Tokens form a directed graph where each layer can reference tokens from the same or lower layers. The depth you choose determines how changes cascade:
| Layer | Contains | Can Reference |
|---|---|---|
| Core | Raw values only | Nothing (leaf nodes) |
| Semantic | Aliases with purpose | Core or other semantic tokens |
| Component | UI-specific bindings | Semantic or core tokens |
This means changing core.color.palette.blue.500 automatically propagates to every semantic token that references it—and from there to every component that uses those semantic tokens. Semantic-to-semantic references let you create shared roles (like status.danger) that multiple components can derive from.
Modular File Architecture
Tokens are split into focused files for maintainability. This reduces merge conflicts and makes ownership clearer:
ui/designTokens/
├── core/
│ ├── color.tokens.json # Palettes, modes, data visualization
│ ├── typography.tokens.json # Font families, weights, scales
│ ├── spacing.tokens.json # Spacing scale (00-10)
│ ├── motion.tokens.json # Durations, easing curves
│ ├── shape.tokens.json # Border radii, border styles
│ └── elevation.tokens.json # Shadows, z-index layers
│
├── semantic/
│ ├── color.tokens.json # Foreground, background, border, status
│ ├── typography.tokens.json # Text styles, hierarchies
│ ├── components/
│ │ └── component.tokens.json
│ └── ...
│
├── designTokens.json # Composed aggregate (build artifact)
└── resolver.json # Theme resolution orderBuild Pipeline Outputs
The tokens compile to multiple formats for different consumers:
- CSS Custom Properties —
--core-color-palette-neutral-500for runtime theming - SCSS Variables — Per-component token files for scoped styling
- TypeScript Types —
TokenPathunion for autocomplete and type safety - Composed JSON — Single artifact for runtime or tooling consumption
The Golden Rule
Never use raw values in components. Always reference tokens so the entire system can be re-themed by changing a single source file.
This isn't just about efficiency—it's a structural guarantee of consistency. Without tokens, a change to a brand color requires hunting down dozens of places where the same decision was repeated. With tokens, a single alias change cascades predictably across the system.
Summary
| Layer | Purpose | Example |
|---|---|---|
| Core | Raw values, no meaning | core.color.palette.blue.500 = #0a65fe |
| Semantic | Purpose + theme awareness | semantic.color.foreground.link = {core.color.palette.red.500} |
| Component | UI-specific composition | semantic.components.button.primary.background |
Deep Dives
The following topics extend this overview into more specialized guidance:
DTCG 1.0 Structured Formats
How we use DTCG 1.0 specification with structured values: color objects, dimension units, and composite tokens.
Read moreCore vs Semantic
How primitives in core.* power purpose-driven semantic.* roles. Why aliases, not copies, improve scale and theming.
Read moreToken Naming & Hierarchy
Conventions for namespacing, depth, and stability. How we avoid collisions and enable discoverability.
Read moreMulti-Brand Theming
How structured tokens enable brand switching, platform variants, and scalable theming across products.
Read moreResolver Module
DTCG 1.0 Resolver Module for context-aware token resolution with sets, modifiers, and resolution orders.
Read moreSchema & Validation
DTCG 1.0 JSON Schema for IntelliSense and AJV validation with structured value enforcement.
Read moreBuild Outputs
What we generate: composed JSON, global CSS vars, component SCSS, and TypeScript token path types.
Read moreAccessibility by Default
Contrast, motion preferences, target sizes—how tokens encode a11y constraints early.
Read more