Design tokens are the atomic values that make up a design system: colors, spacing, typography scales, border radii, shadows, and animation durations. When defined properly, a token like --color-brand is the single source of truth for your primary brand color — change it once and every button, link, and accent across your entire application updates.
Without design tokens, you get color drift: the designer uses #6366F1 in Figma, the developer hardcodes #6063ef in the CSS (typo), and six months later nobody knows which is correct.
This post shows you how to build a token system that is synchronized between Figma and your codebase, using the W3C Design Token format and Tailwind CSS v4's native @theme support.
The W3C Design Token Format
The W3C Community Group has standardized a JSON format for design tokens that tools like Figma, Style Dictionary, and Tokens Studio can read and write:
{
"color": {
"brand": {
"$value": "#6366f1",
"$type": "color",
"$description": "Primary brand color. Used for CTAs and active states."
},
"brand-hover": {
"$value": "#4f46e5",
"$type": "color"
},
"text-primary": {
"$value": "{color.neutral.900}",
"$type": "color"
}
},
"spacing": {
"xs": { "$value": "0.25rem", "$type": "dimension" },
"sm": { "$value": "0.5rem", "$type": "dimension" },
"md": { "$value": "1rem", "$type": "dimension" },
"lg": { "$value": "1.5rem", "$type": "dimension" },
"xl": { "$value": "2rem", "$type": "dimension" },
"2xl": { "$value": "3rem", "$type": "dimension" }
},
"borderRadius": {
"sm": { "$value": "0.25rem", "$type": "dimension" },
"md": { "$value": "0.375rem", "$type": "dimension" },
"lg": { "$value": "0.5rem", "$type": "dimension" },
"full": { "$value": "9999px", "$type": "dimension" }
},
"typography": {
"fontFamily": {
"sans": { "$value": "'Outfit', ui-sans-serif, system-ui", "$type": "fontFamily" },
"mono": { "$value": "'JetBrains Mono', ui-monospace", "$type": "fontFamily" }
},
"fontSize": {
"sm": { "$value": "0.875rem", "$type": "dimension" },
"base": { "$value": "1rem", "$type": "dimension" },
"lg": { "$value": "1.125rem", "$type": "dimension" },
"xl": { "$value": "1.25rem", "$type": "dimension" },
"2xl": { "$value": "1.5rem", "$type": "dimension" },
"3xl": { "$value": "1.875rem", "$type": "dimension" },
"4xl": { "$value": "2.25rem", "$type": "dimension" }
}
},
"shadow": {
"sm": { "$value": "0 1px 2px rgba(0,0,0,0.05)", "$type": "shadow" },
"md": { "$value": "0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06)", "$type": "shadow" },
"lg": { "$value": "0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05)", "$type": "shadow" }
}
}Store this as tokens/tokens.json in your repository.
Syncing Tokens from Figma
Option 1: Tokens Studio Plugin (Recommended)
Tokens Studio for Figma is a Figma plugin that lets designers edit tokens in a structured panel and sync them directly to your GitHub repository:
- Install Tokens Studio in Figma.
- Connect it to your GitHub repository.
- Configure the sync path to
tokens/tokens.json. - Designers update tokens in Figma → Tokens Studio creates a PR with the updated JSON.
Option 2: Figma Variables API (Native Figma)
Figma's native Variables feature (available in Professional plans) stores design tokens as Figma Variables that can be exported via the REST API:
// scripts/sync-figma-tokens.ts
async function fetchFigmaVariables(fileId: string) {
const response = await fetch(
`https://api.figma.com/v1/files/${fileId}/variables/local`,
{ headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }
);
const data = await response.json();
// Transform Figma variables to W3C token format
const tokens: Record<string, object> = {};
for (const [id, variable] of Object.entries(data.meta.variables as Record<string, { name: string; resolvedType: string; valuesByMode: Record<string, { r: number; g: number; b: number; a: number }> }>)) {
const collection = data.meta.variableCollections[variable.name];
const modeId = Object.keys(variable.valuesByMode)[0];
const value = variable.valuesByMode[modeId];
if (variable.resolvedType === 'COLOR') {
const hex = rgbToHex(value.r, value.g, value.b);
tokens[variable.name] = { $value: hex, $type: 'color' };
}
}
return tokens;
}
function rgbToHex(r: number, g: number, b: number): string {
const toHex = (n: number) => Math.round(n * 255).toString(16).padStart(2, '0');
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
Transforming Tokens to Tailwind CSS v4
Use Style Dictionary to transform the W3C JSON format into Tailwind-compatible CSS variables:
pnpm add -D style-dictionary// style-dictionary.config.js
import StyleDictionary from 'style-dictionary';
const sd = new StyleDictionary({
source: ['tokens/tokens.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'ds',
files: [
{
destination: 'app/tokens.css',
format: 'css/variables',
options: {
selector: ':root',
outputReferences: true,
},
},
],
},
},
});
await sd.buildAllPlatforms();This generates app/tokens.css:
:root {
--ds-color-brand: #6366f1;
--ds-color-brand-hover: #4f46e5;
--ds-spacing-xs: 0.25rem;
--ds-spacing-sm: 0.5rem;
--ds-spacing-md: 1rem;
--ds-border-radius-md: 0.375rem;
--ds-font-family-sans: 'Outfit', ui-sans-serif, system-ui;
}Consuming Tokens in Tailwind CSS v4
Import the generated token CSS and map tokens to Tailwind's @theme:
/* app/global.css */
@import "tailwindcss";
@import "./tokens.css"; /* Import generated design tokens */
@theme {
/* Map design tokens to Tailwind utilities */
--color-brand: var(--ds-color-brand);
--color-brand-hover: var(--ds-color-brand-hover);
--spacing-xs: var(--ds-spacing-xs);
--spacing-sm: var(--ds-spacing-sm);
--spacing-md: var(--ds-spacing-md);
--radius-md: var(--ds-border-radius-md);
--font-sans: var(--ds-font-family-sans);
}Now you can use bg-brand, text-brand, p-md, rounded-md as Tailwind utility classes — all driven by the design tokens.
Dark Mode Tokens
// tokens/dark.json — dark mode overrides
{
"color": {
"brand": { "$value": "#818cf8", "$type": "color" },
"background": { "$value": "#0f172a", "$type": "color" },
"text-primary": { "$value": "#f1f5f9", "$type": "color" }
}
}/* Generated dark mode tokens */
[data-theme="dark"] {
--ds-color-brand: #818cf8;
--ds-color-background: #0f172a;
--ds-color-text-primary: #f1f5f9;
}Token Sync CI Pipeline
Automate token synchronization on every merge:
# .github/workflows/token-sync.yml
name: Design Token Sync
on:
push:
paths: ['tokens/**']
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22' }
- run: npm ci
- name: Transform tokens
run: node style-dictionary.config.js
- name: Commit generated CSS
run: |
git config user.name "Token Bot"
git config user.email "tokens@sabaoon.dev"
git add app/tokens.css
git diff --staged --quiet || git commit -m "chore: sync design tokens"
git pushConclusion
Design tokens are the foundation of a scalable design system. By storing tokens in the W3C standard JSON format, syncing them from Figma via Tokens Studio or the Variables API, and transforming them into Tailwind CSS v4 @theme variables with Style Dictionary, you create a single source of truth that keeps designers and developers in sync. When a designer updates the brand color in Figma, a PR is created, a CI job transforms the token, and every element across the entire application reflects the change automatically — with zero manual CSS hunting.