Figma to Code Workflow 2026: Variables, Dev Mode and Tokens Studio
How to wire Figma Variables, Dev Mode, and Tokens Studio into a real design-to-code pipeline that actually ships tokens your codebase can consume.
The State of Figma-to-Code in 2026
The gap between what designers ship in Figma and what engineers actually build has always been embarrassing. In 2026 it's smaller — but only if you've set the pipeline up correctly. Most teams haven't.
Figma Variables (launched properly in 2023, now mature) plus the revamped Dev Mode in Figma 116+ changed everything. You can now define a color as color/brand/primary, attach it to a mode for light and dark, export it via the Style Dictionary format, and have it land directly in your Tailwind config or CSS custom properties file. No more hex values in Slack messages.
In practice, the tooling still requires a bit of manual glue. Tokens Studio (the Figma plugin) is the missing piece that most tutorials skip. It bridges Figma's native Variables API with the W3C Design Token Community Group format, which is what every serious token pipeline actually consumes in 2026.
This article walks through the full stack: structuring Variables in Figma, exporting via Tokens Studio, transforming with Style Dictionary 4, and consuming the output in your React/Tailwind project. We'll also cover where Dev Mode fits in the daily developer workflow — because it's more useful than most devs realise.
Structuring Figma Variables Before You Touch Code
Before any export, the structure of your Variables collection determines whether the output is useful or a mess. Get this wrong and you'll be untangling naming collisions for months. The W3C DTCG format expects a tree: {category}.{concept}.{variant}. Map that to Figma's group separator (/) and you're golden.
Use three collections minimum: Primitives (raw values like blue/500: #3B82F6), Semantics (intent-mapped like color/interactive/default: {blue/500}), and Components (optional, scoped values like button/background/hover). Primitives never change between themes. Semantics do — that's where your light/dark modes live.
Worth noting: Figma enforces that aliases (variable references) only work within the same file as of Figma 116. If your design system spans multiple files, you need the library publish/subscribe flow, which Tokens Studio handles differently than raw Dev Mode exports. Plan around this before you have 400 variables to migrate.
Name your modes consistently. light and dark work. Light Mode and Dark Mode (web) don't — Style Dictionary will choke on the spaces when it builds your output paths. Keep names lowercase, no spaces, hyphens only.
Quick aside: Figma's built-in Variables UI has a 500-variable limit per collection on the Professional plan as of 2026. If you're hitting that, split semantics into sub-collections by category (color, spacing, typography) rather than trying to pack everything in one.
Tokens Studio: The Export Bridge That Actually Works
Tokens Studio (formerly Figma Tokens) is the plugin you want for serious token pipelines. The free tier covers most team needs. Install it, open your Figma file, and it reads your Variables collections automatically. You'll see them mapped to token sets on the left panel.
The key setting is under Sync → GitHub (or any Git provider). Point it at your design-system repo, set the token path to tokens/, and configure it to write W3C DTCG format. Every time a designer pushes a change from Tokens Studio, a PR lands in your repo with the updated JSON. Engineers review token changes the same way they review code. That feedback loop is genuinely valuable.
// tokens/color/primitives.json (W3C DTCG format)
{
"blue": {
"500": {
"$value": "#3B82F6",
"$type": "color"
},
"600": {
"$value": "#2563EB",
"$type": "color"
}
}
}The alias syntax in DTCG uses {dotted.path} references. So your semantic token file looks like this:
// tokens/color/semantic.json
{
"color": {
"interactive": {
"default": {
"$value": "{blue.500}",
"$type": "color"
},
"hover": {
"$value": "{blue.600}",
"$type": "color"
}
}
}
}Tokens Studio resolves those aliases at export time when you're targeting platforms that don't understand references. For platforms that do (CSS custom properties, Tailwind with a plugin), you can keep them as-is and let the consuming layer resolve them at runtime.
Style Dictionary 4: Transforming Tokens to Platform Output
Style Dictionary 4 (released 2024, now the standard) rewrote the transform API. If you're still on v3 configs, the migration is a day of work but worth doing — the new ESM-first approach and built-in DTCG support remove a bunch of custom code most teams were carrying.
Here's a minimal sd.config.mjs that takes your DTCG JSON and outputs CSS custom properties plus a Tailwind extension:
// sd.config.mjs
import StyleDictionary from 'style-dictionary';
const sd = new StyleDictionary({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'empire',
buildPath: 'src/styles/tokens/',
files: [
{
destination: 'variables.css',
format: 'css/variables',
options: { outputReferences: true }
}
]
},
js: {
transformGroup: 'js',
buildPath: 'src/styles/tokens/',
files: [
{
destination: 'tokens.js',
format: 'javascript/es6'
}
]
}
}
});
await sd.buildAllPlatforms();The outputReferences: true option is critical — it writes var(--empire-blue-500) inside your semantic tokens instead of flattening to a raw hex, which means your CSS stays maintainable and your DevTools show readable variable chains. Without it, you lose the semantic layer entirely in the output.
Run node sd.config.mjs in your build pipeline. Wire it as a pre-build step in your package.json: "prebuild": "node sd.config.mjs". The generated CSS file then gets imported in your global stylesheet, and the JS file feeds your Tailwind config. One source, two outputs, zero manual updates.
Honestly, the thing that trips most teams up is multi-mode output. You need a separate file per mode if you want separate CSS files, or you use the options.selector approach to scope modes to a CSS attribute. The second approach is cleaner for theming — :root gets the light tokens, [data-theme="dark"] gets the dark ones.
Dev Mode: What Developers Actually Use It For
Figma's Dev Mode (the </> Dev toggle, costs extra on older plans but bundled in 2026 Organization tiers) surfaces the information developers care about without the visual clutter of design tools. It shows you computed values, attached tokens, and component specs in a clean sidebar.
The underused feature is Code Connect. You write a mapping file that links a Figma component to your actual React component. Once connected, Dev Mode shows real code snippets with correct props instead of generic HTML. For a team using Empire UI, that means a designer can inspect a glassmorphism card in Figma and the code panel shows the actual Empire UI import and the exact props to pass.
// Button.figma.tsx (Code Connect mapping)
import figma from '@figma/code-connect';
import { Button } from '@empire-ui/react';
figma.connect(
Button,
'https://www.figma.com/file/YOUR_FILE_ID?node-id=42:100',
{
props: {
variant: figma.enum('Variant', {
primary: 'primary',
ghost: 'ghost',
outline: 'outline'
}),
size: figma.enum('Size', {
sm: 'sm',
md: 'md',
lg: 'lg'
}),
children: figma.string('Label')
},
example: ({ variant, size, children }) => (
<Button variant={variant} size={size}>{children}</Button>
)
}
);Set this up once per component and you've eliminated the single biggest source of designer-developer miscommunication: "what props does this thing take?" Dev Mode answers that question at inspect time, not at standup.
Worth noting: Code Connect files live in your component repo, not in Figma. They're *.figma.tsx files that you publish via the Figma CLI (figma connect publish). That means they're version-controlled, reviewable, and accurate — as long as someone updates them when the component API changes. Make it part of your component PR checklist.
Wiring It All Into a Real Design System
Pull these pieces together and the full pipeline looks like this: designer edits Variables in Figma → Tokens Studio syncs to GitHub PR → engineer merges → Style Dictionary runs in CI → tokens.css and tailwind.tokens.js are committed → app build picks them up. The whole thing runs without anyone sending a Slack message.
For the Tailwind side, your tailwind.config.ts imports the generated JS tokens and extends the theme. Keep it thin — don't add custom utilities here, just the token values:
// tailwind.config.ts
import tokens from './src/styles/tokens/tokens.js';
import type { Config } from 'tailwindcss';
export default {
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
brand: {
primary: tokens.colorInteractiveDefault,
hover: tokens.colorInteractiveHover
}
},
spacing: {
// map your spacing tokens here
}
}
}
} satisfies Config;Look, this is where most tutorials stop — they show you the token export but don't show you the 8px spacing token becoming space-2 in Tailwind. You need to decide: do you override Tailwind's default scale with your token scale, or extend it? Overriding is cleaner but breaks any third-party component expecting p-4 to mean 16px. Extending is messier but safer when you're using pre-built UI components alongside your design system.
If you're using Empire UI components alongside your own token system, check out the design tokens guide which covers how to scope token namespaces so your custom tokens don't conflict with the component library's internals. The short version: prefix everything — empire-* for the library, acme-* for your product tokens.
For dark mode specifically, the CSS custom properties approach beats Tailwind's class-based dark mode when you have complex token aliasing. Set data-theme on the root, write your dark semantic tokens under that selector, and let the browser handle the cascade. You get instant theme switching without re-rendering the React tree, which matters at 60fps.
Common Failure Modes and How to Avoid Them
The number one failure mode is letting Figma Variables and code tokens drift. This happens when designers add variables directly in Figma without going through Tokens Studio's sync. Enforce the rule: Variables are only added via Tokens Studio, never the native Figma Variables panel. The native panel is for reading values, not authoring them.
Second failure mode: token naming churn. Renaming color/brand/primary to color/action/primary three months in means updating every component that uses the old name. The solution is to treat token names as a public API — deprecate, don't rename. Keep the old alias pointing to the new value for a release cycle, then remove it. Your design system documentation should have a changelog for token renames.
Third: multi-brand support added as an afterthought. If you're going to have more than one visual theme, plan for it in the collection structure from day one. Adding a second brand to an existing primitives/semantics architecture means duplicating the semantics collection and adding a new mode — which Tokens Studio handles fine, but only if you haven't hard-coded brand values in your semantic layer.
Finally, don't skip Code Connect because it "takes too long". A 30-minute investment per component pays off every time a developer has to implement a design. And it forces you to think about whether your component API actually matches the design — which often reveals gaps that would've been bugs in production.
FAQ
Figma's native export is limited — it doesn't write W3C DTCG format and doesn't sync to your repo automatically. Tokens Studio adds the Git sync and the standard token format that Style Dictionary and other transform tools expect. You can get by without it on tiny projects, but any team with more than one designer will outgrow the native export fast.
A Figma Variable like color/brand/primary with value #3B82F6 becomes --color-brand-primary: #3B82F6 via Style Dictionary's css/variables format. Aliases stay as var() references when you set outputReferences: true. The mode becomes a CSS selector scope — light values on :root, dark values on [data-theme="dark"].
Styles are the old system — color styles, text styles, effect styles. They export as static values and don't support modes or aliasing. Variables are the new system and they do. In 2026 you should be migrating Styles to Variables, though Figma still supports both. Variables are what the Dev Mode token panel reads.
Yes, but you need to namespace carefully. Your semantic tokens should describe your product's intent, not the component library's internals. Components that consume token variables by name (like Empire UI's CSS variable hooks) can be overridden by redefining the same custom property in your own stylesheet — that's the standard theming mechanism.