Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

design-token-extract

Installable Ships in design-to-code-builder — or copy the raw skill below.
Open Claude.ai

Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V.

ExperimentalNo security review

Design Token Extraction

Export the complete token layer from Figma Variables to code, validate contrast at extraction time, and generate every format your project consumes. Follows the W3C DTCG 2025.10 stable specification throughout.

Usage

/design-token-extract [figma-url] [options]

If no URL is provided, the skill uses the current Figma selection (Figma MCP active session).

Options:

Flag Values Default Description
--out directory ./tokens/ Where to write output files
--formats comma-separated css,style-dictionary Output formats to generate
--modes comma-separated light Variable modes (collections) to export
--contrast-gate aa, aaa, off aa WCAG contrast gate for semantic color pairs
--prefix string `` Optional prefix for CSS custom property names

Available formats: css, tailwind, scss, dotnet, style-dictionary, dtcg-json

Examples:

/design-token-extract https://figma.com/file/DS123/RBA-Design-System
/design-token-extract --modes light,dark --formats css,tailwind,scss --out src/tokens/
/design-token-extract --formats dotnet --contrast-gate aaa

Phase 1 — Read Figma Variables via MCP

Call get_variable_defs to retrieve the full variable set from the file:

get_variable_defs(node_url: "<figma-url>")

Extract:

  • Variable collections — each collection is a token group (e.g. Color, Spacing, Typography)
  • Modes — each collection can have multiple modes (e.g. Light, Dark, Brand A, Brand B)
  • Variable name and path — Figma uses / as separator (e.g. color/interactive/primary)
  • Resolved values — per mode: hex color, number (for spacing/size), string (for font family)
  • Variable type — COLOR, FLOAT, STRING, BOOLEAN
  • Scopes — Figma variable scope hints (e.g. FILL, STROKE, TEXT_CONTENT)
  • Code syntax — if the design team has set CSS variable names, prefer those

Phase 2 — Classify Token Tier

For each variable, determine its tier based on the name path and Figma group conventions:

Tier Name pattern examples DTCG treatment
Primitive color/blue/500, spacing/4, font/family/base Store as $value literals; NOT exposed as CSS custom properties by default
Semantic color/interactive/primary, color/feedback/error, spacing/component/gap Expose as CSS custom properties; reference primitives via DTCG {primitive.path} syntax
Component button/bg-default, input/border-error Expose as CSS custom properties; reference semantic tokens

If the Figma Variable names do not clearly distinguish tiers, infer:

  • Variables whose value is a direct raw color/number = primitive
  • Variables whose value is another variable (alias) = semantic or component

Phase 3 — Build DTCG Token Structure

Output tokens.json (or tokens/<collection>.tokens.json if multi-file output is preferred).

DTCG 2025.10 format:

{
  "color": {
    "blue": {
      "500": {
        "$type": "color",
        "$value": "#0057B8",
        "$description": "Primary brand blue — primitive, do not use directly in components"
      }
    },
    "interactive": {
      "primary": {
        "$type": "color",
        "$value": "{color.blue.500}",
        "$description": "Default background for primary interactive elements. Contrast pair: on-interactive-primary (#fff) = 6.1:1 AA PASS"
      },
      "primary-dark": {
        "$type": "color",
        "$value": "#003D80",
        "$description": "Dark mode override for primary interactive background. Contrast pair: on-interactive-primary-dark (#fff) = 8.4:1 AA PASS"
      }
    }
  },
  "spacing": {
    "4": {
      "$type": "dimension",
      "$value": "1rem",
      "$description": "Base spacing unit (16px). Maps to Figma spacing/4 variable."
    }
  },
  "typography": {
    "body-md": {
      "$type": "typography",
      "$value": {
        "fontFamily": "{typography.font-family.base}",
        "fontSize": "1rem",
        "fontWeight": "400",
        "lineHeight": "1.5",
        "letterSpacing": "0"
      }
    }
  }
}

Phase 4 — Contrast Validation (semantic color pairs)

For every semantic color token that will be used as a text/background pair, compute the WCAG contrast ratio and embed it in the $description. Flag any failing pairs before writing files.

Finding contrast pairs

Identify pairs by convention:

  • color/on-<X> is the foreground for color/<X> background
  • color/text/<X> on color/surface/<X>
  • color/icon/<X> on color/surface/<X>

Contrast formula

relativeLuminance(hex):
  rgb = [R,G,B] / 255
  linear = x <= 0.04045 ? x/12.92 : ((x+0.055)/1.055)^2.4
  L = 0.2126*R_linear + 0.7152*G_linear + 0.0722*B_linear

contrast(L1, L2) = (lighter + 0.05) / (darker + 0.05)

Gates

Text type Minimum SC
Body text (< 18pt / < 14pt bold) 4.5:1 1.4.3 AA
Large text (≥ 18pt / ≥ 14pt bold) 3:1 1.4.3 AA
UI components (border, icon, focus ring) 3:1 1.4.11
Enhanced body text 7:1 1.4.6 AAA (if --contrast-gate aaa)

Output a contrast report table:

## Contrast Report

| Pair | Foreground | Background | Ratio | Gate | Result |
|------|-----------|------------|-------|------|--------|
| on-interactive-primary / interactive-primary | #ffffff | #0057B8 | 6.1:1 | 4.5:1 | PASS |
| on-interactive-disabled / interactive-disabled | #6B6B6B | #C4C4C4 | 3.2:1 | 4.5:1 | FAIL* |

* FAIL entries block generation by default. Pass --contrast-gate off to write anyway with warnings embedded in the token file $description.


Phase 5 — Generate Output Formats

5.1 CSS custom properties (css)

Write tokens/tokens.css (or tokens.css in --out directory):

:root {
  /* === Semantic: Color === */
  --color-interactive-primary: #0057B8;
  --color-on-interactive-primary: #ffffff;
  --color-focus-ring: #004A9F;

  /* === Semantic: Spacing === */
  --spacing-1: 0.25rem;
  --spacing-2: 0.5rem;
  --spacing-4: 1rem;

  /* === Typography === */
  --typography-body-font-family: 'Inter', sans-serif;
  --typography-body-md-font-size: 1rem;
  --typography-body-md-line-height: 1.5;
}

For dark mode, generate [data-theme='dark'] or @media (prefers-color-scheme: dark) blocks depending on the project's theming strategy (detect from existing CSS if possible).

5.2 Tailwind theme extension (tailwind)

Write tokens/tailwind-tokens.ts:

// tailwind.config.ts — extend this into your config
export const rbaTokens = {
  colors: {
    'interactive-primary': 'var(--color-interactive-primary)',
    'on-interactive-primary': 'var(--color-on-interactive-primary)',
    'focus-ring': 'var(--color-focus-ring)',
  },
  spacing: {
    '1': 'var(--spacing-1)',
    '2': 'var(--spacing-2)',
    '4': 'var(--spacing-4)',
  },
  fontFamily: {
    body: ['var(--typography-body-font-family)', 'sans-serif'],
  },
  fontSize: {
    'body-md': ['var(--typography-body-md-font-size)', { lineHeight: 'var(--typography-body-md-line-height)' }],
  },
};

5.3 SCSS variable map (scss)

Write tokens/_tokens.scss:

// Auto-generated from Figma Variables — do not edit manually
// Run /design-token-extract to regenerate

// Color
$color-interactive-primary: var(--color-interactive-primary) !default;
$color-on-interactive-primary: var(--color-on-interactive-primary) !default;
$color-focus-ring: var(--color-focus-ring) !default;

// Spacing
$spacing-1: var(--spacing-1) !default;
$spacing-4: var(--spacing-4) !default;

// Typography
$typography-body-font-family: var(--typography-body-font-family) !default;

5.4 .NET token class (dotnet)

Write Tokens/DesignTokens.cs:

/// <summary>
/// Design tokens generated from Figma Variables.
/// Auto-generated — do not edit manually. Run /design-token-extract to regenerate.
/// </summary>
public static class DesignTokens
{
    public static class Color
    {
        public const string InteractivePrimary = "var(--color-interactive-primary)";
        public const string OnInteractivePrimary = "var(--color-on-interactive-primary)";
        public const string FocusRing = "var(--color-focus-ring)";
    }
    public static class Spacing
    {
        public const string S1 = "var(--spacing-1)";
        public const string S4 = "var(--spacing-4)";
    }
}

5.5 Style Dictionary config (style-dictionary)

Write tokens/sd.config.json and tokens/tokens.json ready for npx style-dictionary build:

{
  "source": ["tokens/tokens.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "prefix": "rba",
      "buildPath": "src/styles/",
      "files": [{ "destination": "tokens.css", "format": "css/variables" }]
    },
    "js": {
      "transformGroup": "js",
      "buildPath": "src/tokens/",
      "files": [{ "destination": "tokens.js", "format": "javascript/es6" }]
    }
  }
}

Phase 6 — Output Summary

## Token Extraction Summary

**Figma file:** <url>
**Collections exported:** Color, Spacing, Typography, Shadow
**Modes exported:** Light, Dark

**Token counts:**
  - Primitive tokens: N
  - Semantic tokens: N
  - Component tokens: N

**Contrast validation:** N pairs checked
  - PASS: N
  - FAIL: N (listed above — resolve before using in components)

**Files generated:**
  - tokens/tokens.json (DTCG)
  - tokens/tokens.css (CSS custom properties)
  - tokens/tailwind-tokens.ts (Tailwind extension)  [if requested]
  - tokens/_tokens.scss (SCSS map)  [if requested]
  - Tokens/DesignTokens.cs (.NET class)  [if requested]
  - tokens/sd.config.json (Style Dictionary)  [if requested]

**Next steps:**
  - Fix any FAIL contrast pairs in Figma before the next extraction
  - Run /design-system-sync periodically to catch drift
  - Import tokens/tokens.css in your global stylesheet before component styles
Technical details
Plugin
design-to-code-builder
Author
Dakota Smith
Skill name
design-token-extract
Maturity
experimental
Security review
No security review
Owners
  • engineering
  • design
Argument hint
<figma-url-or-current-selection> [--out <dir>] [--formats css,tailwind,scss,dotnet,style-dictionary] [--modes light,dark,brand]
Allowed tools
  • Read
  • Write
  • Edit
  • Glob
  • Grep
  • mcp__figma-dev-mode-mcp-server__get_variable_defs
  • mcp__figma-dev-mode-mcp-server__get_metadata
  • Bash(node *)
  • Bash(npx style-dictionary *)
Source
plugins/design-to-code-builder/skills/design-token-extract/SKILL.md

Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.