Design Token Management
Guidance for implementing design token systems, token schemas, and multi-platform token delivery for design systems.
When to Use This Skill
- Defining design token schemas and structures
- Implementing CSS variable architectures
- Building token transformation pipelines
- Managing token naming conventions
- Integrating with design tools (Figma, Style Dictionary)
Token Architecture
Token Hierarchy
┌─────────────────────────────────────────────────────────────────┐
│ TOKEN HIERARCHY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ PRIMITIVE TOKENS (Raw Values) │
│ ├── colors.blue.500: #3B82F6 │
│ ├── spacing.4: 1rem │
│ └── font-size.base: 16px │
│ │
│ ▼ │
│ │
│ SEMANTIC TOKENS (Meaning/Purpose) │
│ ├── color.action.primary: {colors.blue.500} │
│ ├── spacing.component.padding: {spacing.4} │
│ └── typography.body.size: {font-size.base} │
│ │
│ ▼ │
│ │
│ COMPONENT TOKENS (Component-Specific) │
│ ├── button.primary.background: {color.action.primary} │
│ ├── card.padding: {spacing.component.padding} │
│ └── paragraph.font-size: {typography.body.size} │
│ │
└─────────────────────────────────────────────────────────────────┘
Token Schema
Core Token Model
public class DesignTokenSet
{
public string Name { get; set; } = string.Empty;
public string Version { get; set; } = "1.0.0";
// Token categories
public ColorTokenCategory Colors { get; set; } = new();
public TypographyTokenCategory Typography { get; set; } = new();
public SpacingTokenCategory Spacing { get; set; } = new();
public BorderTokenCategory Borders { get; set; } = new();
public ShadowTokenCategory Shadows { get; set; } = new();
public AnimationTokenCategory Animation { get; set; } = new();
// Semantic mappings
public SemanticTokens Semantic { get; set; } = new();
// Component tokens
public Dictionary<string, ComponentTokens> Components { get; set; } = new();
}
public class ColorTokenCategory
{
// Primitive color scales
public ColorScale Gray { get; set; } = new();
public ColorScale Blue { get; set; } = new();
public ColorScale Green { get; set; } = new();
public ColorScale Red { get; set; } = new();
public ColorScale Yellow { get; set; } = new();
public ColorScale Purple { get; set; } = new();
// Additional custom scales
public Dictionary<string, ColorScale> Custom { get; set; } = new();
}
public class ColorScale
{
public string _50 { get; set; } = string.Empty;
public string _100 { get; set; } = string.Empty;
public string _200 { get; set; } = string.Empty;
public string _300 { get; set; } = string.Empty;
public string _400 { get; set; } = string.Empty;
public string _500 { get; set; } = string.Empty;
public string _600 { get; set; } = string.Empty;
public string _700 { get; set; } = string.Empty;
public string _800 { get; set; } = string.Empty;
public string _900 { get; set; } = string.Empty;
public string _950 { get; set; } = string.Empty;
}
public class TypographyTokenCategory
{
// Font families
public Dictionary<string, string> FontFamily { get; set; } = new()
{
["sans"] = "'Inter', system-ui, sans-serif",
["serif"] = "'Georgia', serif",
["mono"] = "'JetBrains Mono', monospace"
};
// Font sizes
public Dictionary<string, string> FontSize { get; set; } = new()
{
["xs"] = "0.75rem",
["sm"] = "0.875rem",
["base"] = "1rem",
["lg"] = "1.125rem",
["xl"] = "1.25rem",
["2xl"] = "1.5rem",
["3xl"] = "1.875rem",
["4xl"] = "2.25rem"
};
// Font weights
public Dictionary<string, string> FontWeight { get; set; } = new()
{
["normal"] = "400",
["medium"] = "500",
["semibold"] = "600",
["bold"] = "700"
};
// Line heights
public Dictionary<string, string> LineHeight { get; set; } = new()
{
["none"] = "1",
["tight"] = "1.25",
["normal"] = "1.5",
["relaxed"] = "1.75"
};
// Letter spacing
public Dictionary<string, string> LetterSpacing { get; set; } = new()
{
["tight"] = "-0.025em",
["normal"] = "0",
["wide"] = "0.025em"
};
}
public class SpacingTokenCategory
{
public Dictionary<string, string> Scale { get; set; } = new()
{
["0"] = "0",
["px"] = "1px",
["0.5"] = "0.125rem",
["1"] = "0.25rem",
["2"] = "0.5rem",
["3"] = "0.75rem",
["4"] = "1rem",
["5"] = "1.25rem",
["6"] = "1.5rem",
["8"] = "2rem",
["10"] = "2.5rem",
["12"] = "3rem",
["16"] = "4rem",
["20"] = "5rem",
["24"] = "6rem"
};
}
public class SemanticTokens
{
// Action colors
public SemanticColorGroup Action { get; set; } = new()
{
Primary = "{colors.blue.500}",
PrimaryHover = "{colors.blue.600}",
Secondary = "{colors.gray.500}",
SecondaryHover = "{colors.gray.600}",
Danger = "{colors.red.500}",
DangerHover = "{colors.red.600}"
};
// Feedback colors
public SemanticColorGroup Feedback { get; set; } = new()
{
Success = "{colors.green.500}",
Warning = "{colors.yellow.500}",
Error = "{colors.red.500}",
Info = "{colors.blue.500}"
};
// Surface colors
public SemanticSurfaceGroup Surface { get; set; } = new()
{
Background = "#FFFFFF",
Raised = "#F9FAFB",
Overlay = "rgba(0, 0, 0, 0.5)"
};
// Text colors
public SemanticTextGroup Text { get; set; } = new()
{
Primary = "{colors.gray.900}",
Secondary = "{colors.gray.600}",
Muted = "{colors.gray.400}",
Inverse = "#FFFFFF",
Link = "{colors.blue.500}"
};
}
Token JSON Format
Standard Token Format
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"name": "Brand Tokens",
"version": "1.0.0",
"colors": {
"primitive": {
"blue": {
"50": { "value": "#EFF6FF", "type": "color" },
"100": { "value": "#DBEAFE", "type": "color" },
"500": { "value": "#3B82F6", "type": "color" },
"600": { "value": "#2563EB", "type": "color" },
"900": { "value": "#1E3A8A", "type": "color" }
}
},
"semantic": {
"action": {
"primary": {
"value": "{colors.primitive.blue.500}",
"type": "color",
"description": "Primary action color"
},
"primary-hover": {
"value": "{colors.primitive.blue.600}",
"type": "color"
}
}
}
},
"typography": {
"font-family": {
"base": {
"value": "'Inter', system-ui, sans-serif",
"type": "fontFamily"
},
"heading": {
"value": "'Inter', system-ui, sans-serif",
"type": "fontFamily"
}
},
"font-size": {
"sm": { "value": "0.875rem", "type": "fontSize" },
"base": { "value": "1rem", "type": "fontSize" },
"lg": { "value": "1.125rem", "type": "fontSize" },
"xl": { "value": "1.25rem", "type": "fontSize" }
}
},
"spacing": {
"1": { "value": "0.25rem", "type": "spacing" },
"2": { "value": "0.5rem", "type": "spacing" },
"4": { "value": "1rem", "type": "spacing" },
"8": { "value": "2rem", "type": "spacing" }
},
"components": {
"button": {
"primary": {
"background": { "value": "{colors.semantic.action.primary}" },
"background-hover": { "value": "{colors.semantic.action.primary-hover}" },
"text": { "value": "#FFFFFF" },
"padding-x": { "value": "{spacing.4}" },
"padding-y": { "value": "{spacing.2}" },
"border-radius": { "value": "{borders.radius.md}" }
}
}
}
}
Token Transformation Pipeline
Token Processor Service
public class TokenProcessor
{
public async Task<Dictionary<string, string>> ResolveTokensAsync(
DesignTokenSet tokenSet)
{
var resolved = new Dictionary<string, string>();
// First pass: primitive tokens (no references)
ResolvePrimitives(tokenSet, resolved);
// Second pass: semantic tokens (reference primitives)
ResolveSemanticTokens(tokenSet.Semantic, resolved);
// Third pass: component tokens (reference semantic)
foreach (var (componentName, tokens) in tokenSet.Components)
{
ResolveComponentTokens(componentName, tokens, resolved);
}
return resolved;
}
private void ResolveSemanticTokens(
SemanticTokens semantic,
Dictionary<string, string> resolved)
{
// Resolve token references like {colors.blue.500}
foreach (var property in semantic.GetType().GetProperties())
{
var value = property.GetValue(semantic);
if (value is string strValue && strValue.StartsWith("{"))
{
var resolvedValue = ResolveReference(strValue, resolved);
resolved[$"semantic.{property.Name}"] = resolvedValue;
}
}
}
private string ResolveReference(
string reference,
Dictionary<string, string> resolved)
{
// Extract path from {colors.blue.500}
var path = reference.Trim('{', '}');
if (resolved.TryGetValue(path, out var value))
{
return value;
}
throw new TokenResolutionException($"Cannot resolve token reference: {reference}");
}
}
Output Formats
CSS Variables Generator
public class CssTokenGenerator : ITokenOutputGenerator
{
public string Generate(Dictionary<string, string> tokens)
{
var sb = new StringBuilder();
sb.AppendLine(":root {");
foreach (var (name, value) in tokens)
{
var cssVarName = ToCssVariableName(name);
sb.AppendLine($" --{cssVarName}: {value};");
}
sb.AppendLine("}");
return sb.ToString();
}
private string ToCssVariableName(string tokenPath)
{
// colors.blue.500 -> color-blue-500
return tokenPath
.Replace(".", "-")
.Replace("_", "-")
.ToLowerInvariant();
}
}
SCSS Variables Generator
public class ScssTokenGenerator : ITokenOutputGenerator
{
public string Generate(Dictionary<string, string> tokens)
{
var sb = new StringBuilder();
sb.AppendLine("// Design Tokens - Auto-generated");
sb.AppendLine();
// Group by category
var grouped = tokens.GroupBy(t => t.Key.Split('.')[0]);
foreach (var group in grouped)
{
sb.AppendLine($"// {group.Key}");
foreach (var (name, value) in group)
{
var scssVarName = ToScssVariableName(name);
sb.AppendLine($"${scssVarName}: {value};");
}
sb.AppendLine();
}
return sb.ToString();
}
}
Tailwind Config Generator
public class TailwindTokenGenerator : ITokenOutputGenerator
{
public string Generate(Dictionary<string, string> tokens)
{
var config = new
{
theme = new
{
extend = new
{
colors = BuildColorConfig(tokens),
spacing = BuildSpacingConfig(tokens),
fontSize = BuildFontSizeConfig(tokens),
fontFamily = BuildFontFamilyConfig(tokens)
}
}
};
return $"module.exports = {JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true })}";
}
}
Generated Tailwind Output
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'var(--color-action-primary)',
hover: 'var(--color-action-primary-hover)',
},
success: 'var(--color-feedback-success)',
warning: 'var(--color-feedback-warning)',
error: 'var(--color-feedback-error)',
},
spacing: {
'1': 'var(--spacing-1)',
'2': 'var(--spacing-2)',
'4': 'var(--spacing-4)',
'8': 'var(--spacing-8)',
},
fontSize: {
'sm': 'var(--font-size-sm)',
'base': 'var(--font-size-base)',
'lg': 'var(--font-size-lg)',
}
}
}
}
Token API
REST Endpoints
GET /api/tokens # List all token sets
GET /api/tokens/{id} # Get token set by ID
POST /api/tokens # Create token set
PUT /api/tokens/{id} # Update token set
DELETE /api/tokens/{id} # Delete token set
GET /api/tokens/{id}/resolved # Get resolved (flattened) tokens
GET /api/tokens/{id}/css # Get CSS variables output
GET /api/tokens/{id}/scss # Get SCSS variables output
GET /api/tokens/{id}/tailwind # Get Tailwind config
GET /api/tokens/{id}/json # Get JSON format (for tools)
POST /api/tokens/import # Import from Figma/Style Dictionary
POST /api/tokens/validate # Validate token references
Token Response
{
"data": {
"id": "tokens-123",
"name": "Brand Tokens v2",
"version": "2.0.0",
"categories": ["colors", "typography", "spacing", "shadows"],
"tokenCount": 156,
"outputs": {
"css": "/api/tokens/tokens-123/css",
"scss": "/api/tokens/tokens-123/scss",
"tailwind": "/api/tokens/tokens-123/tailwind"
},
"lastModified": "2025-01-15T10:30:00Z"
}
}
Naming Conventions
Token Naming Pattern
Category.Variant.Property.State
Examples:
- color.action.primary.default
- color.action.primary.hover
- color.feedback.success
- typography.heading.size.large
- spacing.component.padding
- border.radius.medium
- shadow.elevation.low
Best Practices
| Convention |
Good |
Bad |
| Semantic naming |
color.action.primary |
color.blue |
| Consistent casing |
font-size-base |
FontSizeBase |
| Hierarchical |
spacing.component.padding |
component-padding |
| Descriptive |
color.text.muted |
color.gray-400 |
| Platform-agnostic |
elevation.low |
box-shadow-1 |
Design Tool Integration
Figma Tokens Import
public class FigmaTokenImporter
{
public async Task<DesignTokenSet> ImportAsync(string figmaFileId)
{
var figmaTokens = await _figmaClient.GetTokensAsync(figmaFileId);
return new DesignTokenSet
{
Name = figmaTokens.Name,
Colors = MapFigmaColors(figmaTokens.Colors),
Typography = MapFigmaTypography(figmaTokens.Typography),
Spacing = MapFigmaSpacing(figmaTokens.Spacing)
};
}
}
Style Dictionary Integration
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/css/",
"files": [{
"destination": "variables.css",
"format": "css/variables"
}]
},
"scss": {
"transformGroup": "scss",
"buildPath": "build/scss/",
"files": [{
"destination": "_variables.scss",
"format": "scss/variables"
}]
}
}
}
Related Skills
multi-site-theming - Per-tenant theme customization
headless-api-design - Token API delivery
content-type-modeling - Token sets as content