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.

1

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
2

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
3

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:

LayerContainsCan Reference
CoreRaw values onlyNothing (leaf nodes)
SemanticAliases with purposeCore or other semantic tokens
ComponentUI-specific bindingsSemantic 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 order

Build Pipeline Outputs

The tokens compile to multiple formats for different consumers:

  • CSS Custom Properties — --core-color-palette-neutral-500 for runtime theming
  • SCSS Variables — Per-component token files for scoped styling
  • TypeScript Types — TokenPath union 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

LayerPurposeExample
CoreRaw values, no meaningcore.color.palette.blue.500 = #0a65fe
SemanticPurpose + theme awarenesssemantic.color.foreground.link = {core.color.palette.red.500}
ComponentUI-specific compositionsemantic.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 more

Core vs Semantic

How primitives in core.* power purpose-driven semantic.* roles. Why aliases, not copies, improve scale and theming.

Read more

Token Naming & Hierarchy

Conventions for namespacing, depth, and stability. How we avoid collisions and enable discoverability.

Read more

Multi-Brand Theming

How structured tokens enable brand switching, platform variants, and scalable theming across products.

Read more

Resolver Module

DTCG 1.0 Resolver Module for context-aware token resolution with sets, modifiers, and resolution orders.

Read more

Schema & Validation

DTCG 1.0 JSON Schema for IntelliSense and AJV validation with structured value enforcement.

Read more

Build Outputs

What we generate: composed JSON, global CSS vars, component SCSS, and TypeScript token path types.

Read more

Accessibility by Default

Contrast, motion preferences, target sizes—how tokens encode a11y constraints early.

Read more

Start Exploring