Figma-to-code workflow: extracting design tokens from Figma Variables, syncing tokens with Style Dictionary, reading Figma files via API, handoff conventions, and maintaining parity between design and implementation. For teams with a designer.
From clarcnpx claudepluginhub marvinrichter/clarc --plugin clarcThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Without a sync pipeline:
--blue-600 to #2563eb in Figma#3b82f6Solution: Figma Variables → export → Style Dictionary → CSS/TS tokens → commit to repo.
Figma Variables map directly to CSS Custom Properties. Establish this convention with your designer:
Figma Variable collection structure:
Primitives (raw values):
colors/blue/500 = #3b82f6
colors/blue/600 = #2563eb
spacing/4 = 16
radius/md = 6
Semantic (light mode):
color/brand = {colors/blue/600}
color/surface = #ffffff
color/text/primary = #111827
Semantic (dark mode): ← same names, different values via mode
color/brand = {colors/blue/500}
color/surface = #0f172a
color/text/primary = #f8fafc
This maps 1:1 to your tokens/colors.css from the design-system skill.
tokens/ JSON files on push// tokens/semantic.json (auto-generated by plugin)
{
"color": {
"brand": { "value": "{colors.blue.600}", "type": "color" },
"surface": { "value": "#ffffff", "type": "color" },
"text": {
"primary": { "value": "#111827", "type": "color" },
"secondary": { "value": "#6b7280", "type": "color" }
}
},
"spacing": {
"4": { "value": "16", "type": "spacing" },
"6": { "value": "24", "type": "spacing" }
}
}
// scripts/sync-tokens.ts
const FIGMA_FILE_ID = process.env.FIGMA_FILE_ID!;
const FIGMA_TOKEN = process.env.FIGMA_ACCESS_TOKEN!;
async function fetchFigmaVariables() {
const response = await fetch(
`https://api.figma.com/v1/files/${FIGMA_FILE_ID}/variables/local`,
{ headers: { 'X-Figma-Token': FIGMA_TOKEN } }
);
return response.json();
}
// Run: npx ts-node scripts/sync-tokens.ts
// Commit the output to version control
Style Dictionary transforms raw JSON tokens into CSS, TypeScript, iOS, Android — one source, many targets.
npm install --save-dev style-dictionary
// style-dictionary.config.js
import StyleDictionary from 'style-dictionary';
const sd = new StyleDictionary({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'ds',
buildPath: 'src/styles/generated/',
files: [
{
destination: 'tokens.css',
format: 'css/variables',
options: { outputReferences: true },
},
],
},
typescript: {
transformGroup: 'js',
buildPath: 'src/styles/generated/',
files: [
{
destination: 'tokens.ts',
format: 'javascript/es6',
},
],
},
},
});
sd.buildAllPlatforms();
# Package.json script
"tokens:build": "node style-dictionary.config.js",
"tokens:sync": "npx ts-node scripts/sync-tokens.ts && npm run tokens:build"
Output (src/styles/generated/tokens.css):
:root {
--ds-color-brand: #2563eb;
--ds-color-surface: #ffffff;
--ds-color-text-primary: #111827;
--ds-spacing-4: 16px;
}
When implementing a component from Figma, extract in this order:
Figma layer: "Card / Product"
├─ Image (rectangle with image fill)
├─ Content
│ ├─ Title (text)
│ ├─ Description (text)
│ └─ Price (text)
└─ Actions
└─ Button / Add to cart
→ Semantic HTML:
<article>
<img />
<div> (content)
<h3>
<p>
<p> (price)
</div>
<footer>
<button>
</footer>
</article>
Figma: inspect → spacing
Padding: 16px all sides = p-4
Gap between elements: 12px = gap-3
Title: Inter 16px / SemiBold / line-height 24px
= text-base font-semibold leading-normal
Price: Inter 14px / Bold / line-height 20px
= text-sm font-bold
Background: #ffffff → bg-surface
Border: #e5e7eb → border-border
Title: #111827 → text-text-primary
Price: #2563eb → text-text-brand
Always ask: "What does this look like on hover / focus / disabled?"
If not in Figma, establish the convention yourself using the design system.
Establish these with your designer once, document in your team wiki:
| Convention | Agreement |
|---|---|
| Spacing | Designer uses 8px grid; developer uses --space-* tokens |
| Colors | Designer uses Variables; developer uses --color-* semantic tokens |
| Typography | Designer uses text styles; developer uses --text-* tokens |
| Breakpoints | Agreed breakpoint names: sm/md/lg/xl |
| States | Designer provides: default, hover, focus, disabled, error |
| Icons | Agreed icon library (Lucide, Heroicons, Phosphor) |
| Images | Designer specifies: aspect ratio, min/max size, object-fit |
| Redline units | Always px in Figma; developer converts to rem |
# .github/workflows/sync-tokens.yml
name: Sync Design Tokens
on:
schedule:
- cron: '0 9 * * 1' # Every Monday morning
workflow_dispatch: # Also runnable manually
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 24 }
- run: npm ci
- name: Fetch tokens from Figma
env:
FIGMA_ACCESS_TOKEN: ${{ secrets.FIGMA_ACCESS_TOKEN }}
FIGMA_FILE_ID: ${{ secrets.FIGMA_FILE_ID }}
run: npm run tokens:sync
- name: Create PR if tokens changed
uses: peter-evans/create-pull-request@v6
with:
title: 'chore: sync design tokens from Figma'
body: 'Auto-generated: design tokens updated from Figma Variables.'
branch: chore/sync-tokens
commit-message: 'chore: sync design tokens from Figma'
text-[#2563eb]) — use tokens