Claude-skill-registry design-tokens-structure
Architects token systems with primitive, semantic, and component layers. Use when structuring tokens from scratch, adding multi-theme support, setting up token aliasing, or organizing token hierarchies.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/design-tokens-structure" ~/.claude/skills/majiayu000-claude-skill-registry-design-tokens-structure && rm -rf "$T"
skills/data/design-tokens-structure/SKILL.mdDesign Tokens Structure
Overview
Establish the architectural foundation for a scalable design token system. Defines the three-layer token hierarchy (primitive → semantic → component) that enables theming, multi-brand support, and maintainable design systems.
When to Use
- Starting a new design system from scratch
- Restructuring an existing token system
- Adding multi-theme or multi-brand support
- Converting hardcoded values to tokens
- Creating a token governance strategy
Implementation Checklist
Copy this checklist when architecting a token system:
Token Architecture Setup: - [ ] Audit existing values and establish naming conventions - [ ] Define primitive tokens (raw values, context-free) - [ ] Define semantic tokens (purpose-based, reference primitives) - [ ] Create theme overrides (dark.json, brand variants) - [ ] Add component tokens for complex stateful components - [ ] Configure build output (CSS variables, Tailwind, JSON)
Quick Reference: Token Layers
| Layer | Also Called | Purpose | Example |
|---|---|---|---|
| Primitive | Core, Base, Global | Raw values, context-free | |
| Semantic | Alias, Purpose, Role | Meaning-based references | |
| Component | Specific, Local | Component-scoped tokens | |
The Three-Layer Architecture
┌─────────────────────────────────────────────────────────┐ │ COMPONENT TOKENS │ │ button-bg, card-border, input-focus-ring │ │ ↓ references │ ├─────────────────────────────────────────────────────────┤ │ SEMANTIC TOKENS │ │ color-primary, color-bg-surface, spacing-page │ │ ↓ references │ ├─────────────────────────────────────────────────────────┤ │ PRIMITIVE TOKENS │ │ blue-500, gray-100, spacing-16, radius-8 │ │ (raw values only) │ └─────────────────────────────────────────────────────────┘
Layer 1: Primitive Tokens
Raw design values with no semantic meaning. These are the building blocks.
Characteristics
- Context-free (no "primary", "background", etc.)
- Named by their intrinsic property (color: hue, spacing: size)
- Never change between themes
- Comprehensive palette of options
Structure
{ "primitive": { "color": { "gray": { "50": { "value": "#f9fafb" }, "100": { "value": "#f3f4f6" }, "200": { "value": "#e5e7eb" }, "300": { "value": "#d1d5db" }, "400": { "value": "#9ca3af" }, "500": { "value": "#6b7280" }, "600": { "value": "#4b5563" }, "700": { "value": "#374151" }, "800": { "value": "#1f2937" }, "900": { "value": "#111827" }, "950": { "value": "#030712" } }, "blue": { "50": { "value": "#eff6ff" }, "100": { "value": "#dbeafe" }, "200": { "value": "#bfdbfe" }, "300": { "value": "#93c5fd" }, "400": { "value": "#60a5fa" }, "500": { "value": "#3b82f6" }, "600": { "value": "#2563eb" }, "700": { "value": "#1d4ed8" }, "800": { "value": "#1e40af" }, "900": { "value": "#1e3a8a" } }, "green": { /* success colors */ }, "red": { /* error colors */ }, "amber": { /* warning colors */ } }, "spacing": { "0": { "value": "0" }, "1": { "value": "0.25rem" }, "2": { "value": "0.5rem" }, "3": { "value": "0.75rem" }, "4": { "value": "1rem" }, "5": { "value": "1.25rem" }, "6": { "value": "1.5rem" }, "8": { "value": "2rem" }, "10": { "value": "2.5rem" }, "12": { "value": "3rem" }, "16": { "value": "4rem" }, "20": { "value": "5rem" }, "24": { "value": "6rem" } }, "radius": { "none": { "value": "0" }, "sm": { "value": "0.125rem" }, "md": { "value": "0.375rem" }, "lg": { "value": "0.5rem" }, "xl": { "value": "0.75rem" }, "2xl": { "value": "1rem" }, "full": { "value": "9999px" } }, "font": { "family": { "sans": { "value": "Inter, system-ui, sans-serif" }, "mono": { "value": "JetBrains Mono, monospace" } }, "size": { "xs": { "value": "0.75rem" }, "sm": { "value": "0.875rem" }, "md": { "value": "1rem" }, "lg": { "value": "1.125rem" }, "xl": { "value": "1.25rem" }, "2xl": { "value": "1.5rem" }, "3xl": { "value": "1.875rem" }, "4xl": { "value": "2.25rem" } }, "weight": { "normal": { "value": "400" }, "medium": { "value": "500" }, "semibold": { "value": "600" }, "bold": { "value": "700" } } } } }
Layer 2: Semantic Tokens
Purpose-based tokens that reference primitives. These tokens change between themes.
Characteristics
- Named by purpose/role, not appearance
- Reference primitive tokens only
- The only layer that changes per theme
- Describe "what for", not "what it looks like"
Structure
{ "semantic": { "color": { "bg": { "primary": { "value": "{primitive.color.gray.50}" }, "secondary": { "value": "{primitive.color.gray.100}" }, "tertiary": { "value": "{primitive.color.gray.200}" }, "inverse": { "value": "{primitive.color.gray.900}" }, "brand": { "value": "{primitive.color.blue.500}" } }, "text": { "primary": { "value": "{primitive.color.gray.900}" }, "secondary": { "value": "{primitive.color.gray.600}" }, "tertiary": { "value": "{primitive.color.gray.500}" }, "inverse": { "value": "{primitive.color.gray.50}" }, "brand": { "value": "{primitive.color.blue.600}" }, "link": { "value": "{primitive.color.blue.600}" } }, "border": { "primary": { "value": "{primitive.color.gray.200}" }, "secondary": { "value": "{primitive.color.gray.300}" }, "focus": { "value": "{primitive.color.blue.500}" } }, "status": { "success": { "value": "{primitive.color.green.500}" }, "warning": { "value": "{primitive.color.amber.500}" }, "error": { "value": "{primitive.color.red.500}" }, "info": { "value": "{primitive.color.blue.500}" } }, "interactive": { "primary": { "value": "{primitive.color.blue.500}" }, "primary-hover": { "value": "{primitive.color.blue.600}" }, "primary-active": { "value": "{primitive.color.blue.700}" }, "secondary": { "value": "{primitive.color.gray.100}" }, "secondary-hover": { "value": "{primitive.color.gray.200}" } } }, "spacing": { "page": { "value": "{primitive.spacing.6}" }, "section": { "value": "{primitive.spacing.12}" }, "element": { "value": "{primitive.spacing.4}" }, "inline": { "value": "{primitive.spacing.2}" } }, "radius": { "interactive": { "value": "{primitive.radius.md}" }, "container": { "value": "{primitive.radius.lg}" }, "pill": { "value": "{primitive.radius.full}" } } } }
Dark Theme Override
{ "semantic": { "color": { "bg": { "primary": { "value": "{primitive.color.gray.950}" }, "secondary": { "value": "{primitive.color.gray.900}" }, "tertiary": { "value": "{primitive.color.gray.800}" }, "inverse": { "value": "{primitive.color.gray.50}" } }, "text": { "primary": { "value": "{primitive.color.gray.50}" }, "secondary": { "value": "{primitive.color.gray.400}" }, "tertiary": { "value": "{primitive.color.gray.500}" }, "inverse": { "value": "{primitive.color.gray.900}" } }, "border": { "primary": { "value": "{primitive.color.gray.800}" }, "secondary": { "value": "{primitive.color.gray.700}" } } } } }
Layer 3: Component Tokens
Component-specific tokens that reference semantic tokens. Optional but powerful for complex components.
Characteristics
- Scoped to a specific component
- Reference semantic tokens (rarely primitives)
- Enable component-level customization
- Used for complex, stateful components
Structure
{ "component": { "button": { "primary": { "bg": { "value": "{semantic.color.interactive.primary}" }, "bg-hover": { "value": "{semantic.color.interactive.primary-hover}" }, "text": { "value": "{semantic.color.text.inverse}" }, "border": { "value": "transparent" }, "radius": { "value": "{semantic.radius.interactive}" }, "padding-x": { "value": "{primitive.spacing.4}" }, "padding-y": { "value": "{primitive.spacing.2}" } }, "secondary": { "bg": { "value": "{semantic.color.interactive.secondary}" }, "bg-hover": { "value": "{semantic.color.interactive.secondary-hover}" }, "text": { "value": "{semantic.color.text.primary}" }, "border": { "value": "{semantic.color.border.primary}" } }, "disabled": { "bg": { "value": "{primitive.color.gray.100}" }, "text": { "value": "{primitive.color.gray.400}" } } }, "input": { "bg": { "value": "{semantic.color.bg.primary}" }, "text": { "value": "{semantic.color.text.primary}" }, "placeholder": { "value": "{semantic.color.text.tertiary}" }, "border": { "value": "{semantic.color.border.primary}" }, "border-focus": { "value": "{semantic.color.border.focus}" }, "radius": { "value": "{semantic.radius.interactive}" }, "padding-x": { "value": "{primitive.spacing.3}" }, "padding-y": { "value": "{primitive.spacing.2}" } }, "card": { "bg": { "value": "{semantic.color.bg.primary}" }, "border": { "value": "{semantic.color.border.primary}" }, "radius": { "value": "{semantic.radius.container}" }, "padding": { "value": "{semantic.spacing.element}" }, "shadow": { "value": "{primitive.shadow.md}" } } } }
CSS Output
Generated Variables
/* Primitives - available but rarely used directly */ :root { --primitive-color-gray-50: #f9fafb; --primitive-color-gray-900: #111827; --primitive-color-blue-500: #3b82f6; --primitive-spacing-4: 1rem; /* ... */ } /* Semantic - the main tokens you use */ :root { --color-bg-primary: var(--primitive-color-gray-50); --color-text-primary: var(--primitive-color-gray-900); --color-interactive-primary: var(--primitive-color-blue-500); --spacing-element: var(--primitive-spacing-4); /* ... */ } /* Dark theme overrides semantic only */ [data-theme="dark"] { --color-bg-primary: var(--primitive-color-gray-950); --color-text-primary: var(--primitive-color-gray-50); /* primitives stay the same */ } /* Component tokens (optional) */ :root { --button-primary-bg: var(--color-interactive-primary); --button-primary-text: var(--color-text-inverse); --card-bg: var(--color-bg-primary); --card-padding: var(--spacing-element); }
Usage in Components
/* Use semantic tokens */ .card { background: var(--color-bg-primary); color: var(--color-text-primary); border: 1px solid var(--color-border-primary); padding: var(--spacing-element); } /* Or use component tokens if defined */ .card { background: var(--card-bg); padding: var(--card-padding); } /* Never use primitives directly in components */ /* ❌ Bad */ .card { background: var(--primitive-color-gray-50); }
File Organization
Recommended Structure
tokens/ ├── primitive/ │ ├── colors.json │ ├── spacing.json │ ├── typography.json │ ├── radius.json │ └── shadows.json ├── semantic/ │ ├── light.json # Light theme semantic mappings │ └── dark.json # Dark theme overrides ├── component/ │ ├── button.json │ ├── input.json │ └── card.json └── index.json # Combines all for build
Flat vs Nested
Nested (Recommended for large systems):
{ "color": { "bg": { "primary": { "value": "..." } } } }
Output:
--color-bg-primary
Flat (Simpler for small systems):
{ "color-bg-primary": { "value": "..." } }
Output:
--color-bg-primary
Naming Conventions
Pattern: {category}-{property}-{variant}-{state}
{category}-{property}-{variant}-{state}| Category | Examples |
|---|---|
| color | , |
| spacing | , |
| radius | , |
| font | , |
| shadow | , |
Semantic Naming Guidelines
| Use | Avoid |
|---|---|
| |
| |
| |
| |
| |
When to Add Each Layer
| Situation | Layers Needed |
|---|---|
| Simple app, single theme | Primitive + Semantic |
| Multi-theme (light/dark) | Primitive + Semantic (per theme) |
| Complex components | All three layers |
| Multi-brand (white-label) | All three + brand-specific overrides |
| Design tool sync | Primitive only to start |
Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Semantic references semantic | Circular/complex chains | Semantic → Primitive only |
| Using primitives in components | Breaks theming | Use semantic tokens |
| Color names in semantic | Leaks visual info | Use purpose names |
| Too many component tokens | Maintenance burden | Only for complex states |
| Skipping semantic layer | Can't theme | Always have semantic layer |
Migrating Existing Tokens
Step 1: Audit Current Usage
Find all hardcoded values and existing variables.
Step 2: Create Primitive Layer
Extract unique values into primitives.
Step 3: Create Semantic Layer
Map primitives to purposes.
Step 4: Update Components
Replace hardcoded values with semantic tokens.
Step 5: Add Themes
Create theme-specific semantic overrides.
/* Before */ .button { background: #3b82f6; color: white; } /* After */ .button { background: var(--color-interactive-primary); color: var(--color-text-inverse); }