Design tokens are the shared names for your design decisions: color.brand.500, space.md, radius.pill. Keeping them in sync between Figma and code is where most design systems drift. Here is a workflow that keeps one source of truth.
1. Structure your Variables for code
- Primitives collection: raw values (violet/500, gray/900, space/4). One mode.
- Semantic collection: meaning, not value (surface, text, accent, border). Modes for Light and Dark, each aliasing a primitive.
- Name with slashes in Figma (color/brand/500). They become dots or dashes in code.
2. Export
Use a Variables export that preserves aliases and modes — either a plugin that writes the W3C Design Tokens format or one that exports collections and modes as JSON. Aliases matter: if surface points to paper/50, code should say so instead of copying the hex value.
3. Know the W3C format
{
"color": {
"$type": "color",
"brand": { "500": { "$value": "#8B6CF0" } },
"action": { "primary": { "$value": "{color.brand.500}" } }
}
}Each token has a $value and a $type (which can be inherited from its group). Aliases are written as {group.token}.
4. Generate Tailwind v4 and CSS
Tailwind v4 is configured in CSS with an @theme block. Namespaces decide which utilities exist: --color-* creates bg-*, text-* and border-* colors, --spacing-* feeds padding and margin, --radius-* feeds rounded-*, --text-* sets font sizes.
@import "tailwindcss";
@theme {
--color-brand-500: #8B6CF0;
--color-action-primary: #8B6CF0;
--spacing-md: 16px;
--radius-pill: 999px;
}5. Light and dark modes
Generate one CSS block per mode and switch with a data attribute: :root for light and [data-theme="dark"] for dark. Because components use semantic names (surface, text), nothing else changes.
Keep it in sync
Treat the token file as code: commit it, review changes in pull requests, and regenerate outputs in CI. Designers change Variables, export, and a pull request shows exactly which tokens moved.