Back to Tools

Figma Design System to LLM Integration Guide

A comprehensive guide for building, structuring, and exporting Figma design systems to LLMs using MCP and other approaches.

Phase 1: Visual Design Foundation

Step 1.1: Audit and Inventory

Goal: Understand what you're designing for before you build anything

Why this matters: Think of this like taking inventory before organizing a kitchen. You need to know what pots, pans, and ingredients you have before deciding how to arrange your cabinets. Similarly, you need to understand your design landscape before building a system.

What to Document:

1. Platforms (Where will your designs live?)
Examples:
✓ Web (desktop browser)
✓ Web (mobile browser)
✓ iOS native app
✓ Android native app
✓ Desktop application (Mac/Windows)
✓ Email templates
✓ Marketing landing pages

Why it matters: Each platform has different constraints:

  • Web: Must work in different browsers, responsive sizing
  • iOS: Follows Apple's Human Interface Guidelines, specific touch targets
  • Android: Follows Material Design principles, different screen densities
  • Email: Very limited CSS support, must work in Outlook

Quick tip:

Open your product on different devices and screenshot what looks different. These differences will inform your system.

2. Product Surfaces (Different areas of your product)
Examples:
✓ Marketing website (public-facing)
✓ Main application (logged-in users)
✓ Admin dashboard (internal tools)
✓ Mobile app
✓ Documentation site
✓ Email notifications

Why it matters: Different surfaces often need different visual weights:

  • Marketing sites are usually more colorful and bold
  • Applications are more subdued and functional
  • Admin tools prioritize information density

Quick tip:

Make a simple list. Walk through your product and write down every distinct "area" or "section" that feels different.

3. Brand Requirements (Visual identity consistency)

Single Brand Example:

Company: Acme Corp
Products: All use same blue, same logo, same fonts
Need: 1 cohesive design system

Quick tip:

Document your existing brand guidelines (logo colors, fonts, etc.) before starting. This will inform your color and typography decisions.

4. Catalog Existing Patterns (What do you already have?)

How to do this as a beginner:

a) Take screenshots of every unique element:

  • Every button style you see
  • Every form input
  • Every card or container
  • Every color used
  • Every font size

b) Group similar items:

Buttons I found:
- Blue button with white text (appears 47 times)
- White button with blue text (appears 23 times)
- Red button with white text (appears 8 times)
- Green button with white text (appears 12 times)
- Link that looks like button (appears 34 times)

c) Count inconsistencies:

Button corner roundness:
- Completely square corners (0px radius) - 15 instances
- Slightly rounded (4px) - 32 instances
- Medium rounded (8px) - 41 instances
- Very rounded (12px) - 8 instances

Problem: We have 4 different button roundness levels!
Solution: Design system will standardize to 1 or 2 options

Quick tip:

Use a tool like Figma's "Inspect" feature or a browser inspector to see exact values. Write them all down - even if they seem chaotic.

5. Accessibility Requirements (Who needs to use your product?)

What is WCAG?

Web Content Accessibility Guidelines - basically rules to make sure everyone can use your product, including people with:

  • Vision impairments (low vision, color blindness, blindness)
  • Hearing impairments
  • Motor impairments (difficulty using a mouse)
  • Cognitive impairments

Levels Explained:

  • Level A: Bare minimum (you must do this)
  • Level AA: Standard for most businesses (recommended)
  • Level AAA: Highest standard (nice to have)

Common Requirements You'll Deal With:

1. Color Contrast:

Bad:  Light gray text (#999) on white background
Good: Dark gray text (#333) on white background

Rule: Text must have 4.5:1 contrast ratio
Tool: Use WebAIM Contrast Checker

2. Touch Target Size:

Bad:  Button is 20px x 20px (too small)
Good: Button is 44px x 44px minimum

Why: People with motor impairments or thick fingers need larger targets

3. Keyboard Navigation:

Must be able to:
- Tab through all interactive elements
- See which element is focused (visible outline)
- Activate buttons with Enter/Space
- Close modals with Escape

Quick tip:

Try using your product with only your keyboard (no mouse). Any time you get stuck, that's an accessibility problem to document.

Step 1.2: Visual Design Primitives

Goal: Build your basic building blocks - the "atoms" of your design

Think of it like cooking: Before you can make a cake, you need basic ingredients (flour, sugar, eggs). Before you can make a design system, you need basic visual ingredients (colors, fonts, spacing).

COLOR - Your Visual Palette

What you're building: A set of approved colors that everything in your system will use.

1. Base Palette (Brand Colors)

These are THE colors that represent your brand:

Real Example - Stripe:
Primary: #635BFF (purple - their signature color)
Used for: Main buttons, links, brand moments

Real Example - Notion:
Primary: #000000 (black)
Secondary: #EB5757 (red)
Used for: Headers, important actions

How to choose (for beginners):

  • Start with your logo colors
  • Pick 1-2 primary colors that represent your brand
  • Pick 1-2 accent colors for variety
  • Keep it simple: 3-5 brand colors maximum

Quick tip:

Go to your company's brand guidelines or ask marketing for official brand colors. They'll usually give you hex codes like #3B82F6.

2. Semantic Colors (Colors with Meaning)

These colors communicate specific meanings to users:

Success (Green family):
#10B981 - "Your payment went through!"
#DEF7EC - Light green background for success messages

Warning (Yellow/Orange family):
#F59E0B - "Please review this before continuing"
#FEF3C7 - Light yellow background for warnings

Error (Red family):
#EF4444 - "Something went wrong"
#FEE2E2 - Light red background for errors

Info (Blue family):
#3B82F6 - "Here's some helpful information"
#DBEAFE - Light blue background for info messages

Why these specific colors:

  • Green = success (universal - think traffic lights)
  • Red = danger/error (universal)
  • Yellow = caution (universal)
  • Blue = informational (neutral, trustworthy)

Quick tip:

Don't reinvent the wheel. Users expect red for errors and green for success. Fight this expectation only with good reason.

3. Neutral Scale (Grays/Backgrounds)

This is your most-used color set. You need a range from white to black:

Real example scale (Tailwind-style):

White → Light Gray → Medium Gray → Dark Gray → Black
#FFFFFF (backgrounds)
#F9FAFB (subtle backgrounds)
#F3F4F6 (borders, dividers)
#E5E7EB (disabled buttons)
#D1D5DB (borders)
#9CA3AF (placeholder text)
#6B7280 (secondary text)
#4B5563 (body text)
#374151 (headings)
#1F2937 (important text)
#111827 (maximum contrast)
#000000 (pure black - rarely used)

Why so many grays? Each gray has a job:

  • Lightest grays: backgrounds, subtle divisions
  • Medium grays: borders, inactive elements
  • Dark grays: body text, secondary information
  • Darkest grays: headings, primary information

Quick tip:

Use a tool like UI Colors or Tailwind's color generator. Enter your base gray and it generates the whole scale.

TYPOGRAPHY - Your Text Styles

What you're building: Rules for all text in your product.

1. Font Families

Real Example - GitHub:
Primary: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica
(This uses the system font - different on Mac vs Windows)

Real Example - Notion:
Primary: "Inter" (custom font they host)

Real Example - Code Editor:
Monospace: "SF Mono", "Monaco", "Courier" (for code)

How to choose:

  • System Fonts (Free, fast, familiar)
    • Mac: SF Pro, Helvetica
    • Windows: Segoe UI
    • Cross-platform: -apple-system, system-ui
  • Google Fonts (Free, easy)
    • Inter (modern, clean)
    • Roboto (neutral)
    • Open Sans (friendly)
  • Custom Fonts (Brand-specific, costs money)
    • Requires licensing
    • Must host font files
    • Slower to load

Quick tip:

When in doubt, use Inter from Google Fonts. It's free, looks professional, and works everywhere.

2. Type Scale (Font Sizes)

You need a range of sizes from small fine print to large headings:

Real Example Scale:

Name        Size    Use Case                    Example
xs          12px    Fine print, captions        "© 2025 Company"
sm          14px    Small labels                Form labels
base        16px    Body text (DEFAULT)         Paragraphs
lg          18px    Large body, intro text      Article lead
xl          20px    Small headings              Card titles
2xl         24px    Section headings            <h3>
3xl         30px    Page subheadings            <h2>
4xl         36px    Page headings               <h1>
5xl         48px    Display text                Landing page hero
6xl         60px    Large display               Marketing headlines

The Golden Rule:

  • Your base size should be 16px (readable on all devices)
  • Each step up should be noticeably bigger (1.25x or 1.5x ratio)
  • Never go smaller than 12px (accessibility issue)

Quick tip:

Use a type scale calculator like Type-Scale.com. Pick "Major Third" ratio (1.25) for conservative, "Perfect Fourth" (1.33) for more dramatic.

SPACING - How Things Breathe

What you're building: A system for all gaps, margins, and padding in your product.

The Magic Number: Base Unit

Pick one number as your foundation. Everything else multiplies from it.

Most Common: 8px
Why? Divides evenly, works with most screen sizes

Scale from 8px:
4px   (half)         Tight spacing between related items
8px   (1x)          Small gaps, compact layouts
12px  (1.5x)        In-between size
16px  (2x)          Default spacing (most common)
24px  (3x)          Medium spacing between sections
32px  (4x)          Large gaps, breathing room
48px  (6x)          Section separators
64px  (8x)          Major sections
96px  (12x)         Between page sections
128px (16x)         Hero section padding

Quick tip:

When in doubt, use 16px (2x your base). It's the Goldilocks spacing - not too tight, not too loose.

Step 1.3: Figma File Organization Best Practices

Goal: Set up your Figma files for easy token export and component management

Why this matters: A well-organized Figma file structure makes token creation, component building, and export 10x easier. Set this up correctly now to save hours later.

Recommended File Structure

📁 Design System (Main File)
├── 📄 Page: 🎨 Foundation
│   ├── Frame: Color Primitives (all raw colors)
│   ├── Frame: Color Semantic (purpose-based colors)
│   ├── Frame: Typography Scale (all text styles)
│   ├── Frame: Spacing Scale (spacing documentation)
│   └── Frame: Elevation/Shadows (shadow tokens)
│
├── 📄 Page: 🧱 Components
│   ├── Frame: Atoms (buttons, inputs, icons)
│   ├── Frame: Molecules (search bars, cards)
│   └── Frame: Organisms (navigation, headers)
│
├── 📄 Page: 📐 Layouts
│   ├── Frame: Grid System
│   ├── Frame: Breakpoints
│   └── Frame: Page Templates
│
└── 📄 Page: 📖 Documentation
    ├── Frame: Guidelines
    ├── Frame: Do's and Don'ts
    └── Frame: Component Usage Examples

Variables Panel Organization

When creating Variables in Figma, organize them into Collections:

Collection: Primitives
├── primitive/color/blue/50
├── primitive/color/blue/500
├── primitive/color/blue/900
├── primitive/spacing/xs (4px)
├── primitive/spacing/sm (8px)
└── ...

Collection: Semantic
├── semantic/background/primary (→ primitive/color/gray/50)
├── semantic/text/primary (→ primitive/color/gray/900)
├── semantic/text/danger (→ primitive/color/red/600)
└── ...

Collection: Component
├── component/button/background/primary (→ semantic/action/primary)
├── component/button/text/primary (→ semantic/text/inverse)
└── ...

Naming Conventions for Variables

Use forward slashes (/) for hierarchy:

✓ GOOD:
primitive/color/blue/500
semantic/text/primary
component/button/background/hover

✗ BAD:
blue-500 (no hierarchy)
textPrimary (camelCase instead of slash hierarchy)
btn-bg-hover (unclear abbreviations)

Component Organization Tips

  • One component per frame: Keep each component in its own frame for easy navigation
  • Show all variants: Display all size/state variations in one place
  • Use Auto Layout: Makes components responsive and easier to maintain
  • Link to variables: Don't hardcode values—always reference variables
  • Document usage: Add descriptions to component properties

Pre-Export Checklist

Before exporting tokens or sharing with developers, verify:

  • All variables are properly named with hierarchy (slash notation)
  • Variables are organized into logical Collections
  • Semantic tokens reference primitive tokens (not hardcoded values)
  • Component tokens reference semantic tokens
  • Components use variables for all properties (colors, spacing, sizing)
  • Dark mode variables are set up (if needed)
  • No duplicate or conflicting variable names

Pro tip for teams:

Create a "Design System Starter Template" with this structure already set up. Share it with your team so everyone starts with the same organization. This ensures consistency across projects.

Phase 2: Design Tokens & Variables

Design tokens are the foundation of a scalable design system. They transform your visual primitives into reusable, platform-agnostic values that can be shared across design and code.

What are Design Tokens?

Think of them like variables in code. Instead of writing the color blue (#3B82F6) everywhere, you create a token called "primary-blue" and reference that. If you need to change the shade of blue later, you change it once, and it updates everywhere.

Without tokens:
button-color: #3B82F6
link-color: #3B82F6
badge-color: #3B82F6
(Change requires updating 500+ instances)

With tokens:
token: primary-blue = #3B82F6
button-color: primary-blue
link-color: primary-blue
badge-color: primary-blue
(Change token once, updates everywhere)

Figma Variables vs Figma Tokens Plugin

There are two main approaches to managing design tokens in Figma. Understanding the difference is important:

Figma Variables (Native, Recommended)

Figma's built-in Variables system is now the standard way to manage design tokens. Introduced in 2023, it's native to Figma and requires no plugins.

  • Native feature - No plugin required, built into Figma
  • Type support: Colors, numbers, strings, booleans
  • Collections & Modes: Organize tokens and support themes (light/dark)
  • Native export: DTCG JSON format (File → Variables → Export)
  • Future-proof: Officially supported by Figma

Quick tip:

Access the Variables panel in Figma: View → Variables (or Option + Shift + K on Mac / Ctrl + Shift + K on Windows). This is where you'll create and manage all your design tokens.

Figma Tokens Plugin (Community, Legacy)

Before Figma Variables existed, the community-built "Figma Tokens" plugin was the standard approach. It's still widely used, especially in legacy projects.

  • Plugin required - Must install from Figma Community
  • More token types: Includes typography, spacing, sizing, borders, shadows
  • Git sync: Can sync directly to GitHub/GitLab
  • JSON format: Custom format, requires Style Dictionary transformation
  • Legacy support: Many existing design systems still use this

Which should you use?

New projects: Use Figma Variables. It's native, simpler, and officially supported.

Existing projects: If you're already using Figma Tokens plugin and it's working well, migration isn't urgent. Both approaches work, but plan to eventually migrate to Variables.

Token Hierarchy: The Three-Layer System

Layer 1: PRIMITIVES (Raw values)
├── What: Actual colors (#3B82F6), actual numbers (16px)
├── Who edits: Design system managers only
├── How often: Rarely (maybe once a year for rebrand)
└── Example: primitive/color/blue/500 = #3B82F6

        ↓ Referenced by ↓

Layer 2: SEMANTIC (Purpose-based)
├── What: References to primitives with meaningful names
├── Who edits: Design system managers
├── How often: Occasionally (quarterly adjustments)
└── Example: semantic/text/primary = primitive/color/gray/900

        ↓ Referenced by ↓

Layer 3: COMPONENT (Component-specific)
├── What: References to semantic tokens for specific components
├── Who edits: Component designers
├── How often: Frequently (when building/updating components)
└── Example: component/button/text/default = semantic/text/inverse

Phase 3: Component Architecture

With your tokens in place, it's time to build components that leverage them. Proper component architecture ensures consistency and makes maintenance effortless.

Component Hierarchy (Atomic Design)

Atoms (Basic building blocks)
├── Button
├── Input
├── Icon
├── Label
├── Badge
└── Avatar

Molecules (Simple combinations)
├── Input with Label
├── Button Group
├── Search Field
└── Select Dropdown

Organisms (Complex patterns)
├── Navigation Bar
├── Form Section
├── Card with Actions
└── Data Table

Component Properties Strategy

Use Figma's Component Properties to create flexible, reusable components:

  • Variants: Size (sm, md, lg), State (default, hover, active, disabled)
  • Boolean: Icon, Label, Badge visibility toggles
  • Text: Label content, Placeholder text
  • Instance Swap: Icon selection, nested components

Quick tip:

Every component property should reference variables. Button background → component/button/background/default. This ensures your components automatically adapt when tokens change.

Phase 4: Export Strategy

Figma now supports native export of design tokens using the DTCG (Design Tokens Community Group) format, making it easy to share your design system with code.

Native Figma Export (DTCG Format)

Export your variables:

  • File → Variables → Export variables
  • Choose DTCG JSON format
  • Exports all collections and modes

DTCG JSON Structure

{
  "primitive": {
    "color": {
      "blue": {
        "50": {
          "$type": "color",
          "$value": "#eff6ff"
        },
        "500": {
          "$type": "color",
          "$value": "#3b82f6"
        }
      }
    }
  },
  "semantic": {
    "background": {
      "primary": {
        "$type": "color",
        "$value": "{primitive.color.gray.50}"
      }
    }
  }
}
json

Token Validation & Quality Checks

After exporting tokens, validate them to catch errors before they reach your codebase.

Manual Validation Checklist

  • JSON validity: Ensure exported JSON parses without errors
  • Token references: All {references} point to existing tokens
  • Color format: Colors are in hex (#RRGGBB) or valid CSS format
  • Naming consistency: All tokens follow your naming convention
  • No duplicates: No duplicate token names across collections
  • Type correctness: $type matches value format (color, dimension, etc.)

Common Export Errors

❌ Error 1: Broken Reference
{
  "$value": "{primitive.color.blue.500}"
}
// But primitive.color.blue.500 doesn't exist

✓ Fix: Create the missing token or update the reference

❌ Error 2: Circular Reference
semantic.text.primary → semantic.text.body → semantic.text.primary

✓ Fix: Break the circle by referencing primitives

❌ Error 3: Wrong Type
{
  "$type": "dimension",
  "$value": "#3B82F6"  // This is a color, not a dimension!
}

✓ Fix: Correct the $type to "color"

Testing Token Integration

After validation, test tokens in your codebase:

  • 1.Import test: Try importing tokens into your build system
  • 2.CSS generation: Convert to CSS variables and verify output
  • 3.Visual test: Apply tokens to a test page and compare to Figma
  • 4.Dark mode check: If using modes, verify theme switching works
  • 5.Contrast audit: Run accessibility contrast checks on colors

Quick tip:

Create a simple HTML page that displays all your tokens (color swatches, text samples, spacing examples). This visual reference makes it easy to spot errors and verify tokens match your Figma designs.

Phase 5: LLM Integration via MCP

Last updated: November 2025 | MCP landscape evolves rapidly—verify latest documentation

The Model Context Protocol (MCP) enables AI assistants to access and work with your design system directly. There are two complementary approaches you'll use together.

Understanding the Two Types of MCP Servers

It's crucial to understand that you'll likely use BOTH types of MCP servers in your workflow:

Key Distinction:

  • 1.Figma's Official MCP Server - Pulls design data FROM Figma (files, variables, components, frames)
  • 2.Custom Design System MCP Server - Exposes YOUR design system TO LLMs (guidelines, tokens, patterns, rules)
  • Approach 1: Figma's Official MCP Server (HTTP/SSE transport, connects directly to your Figma files, works with VS Code, Cursor, Windsurf, and Claude Code CLI)
  • Approach 2: Custom Design System MCP Server (stdio transport, exposes your design system's rules and patterns, works with Claude Desktop and other stdio-compatible clients)

Approach 1: Figma's Official MCP Server

Figma's official MCP server connects LLMs directly to your Figma files to pull design data, generate code from frames, and access variables and components.

What This Gives You:

  • Generate code from selected Figma frames
  • Pull in variables, components, and layout data
  • Access Figma file structure and design properties
  • No authentication required (uses Figma's built-in auth)

Two Connection Methods

Remote Server (Hosted by Figma):

URL: https://mcp.figma.com/mcp
Benefits: Always up-to-date, no local installation needed
Transport: Streamable HTTP with SSE
Supported: VS Code, Cursor, Windsurf, Claude Code CLI

Desktop Server (Local Figma App):

URL: http://127.0.0.1:3845/mcp
Benefits: Works offline, faster responses
Requirement: Figma Desktop app must be running
Transport: Streamable HTTP with SSE
Supported: VS Code, Cursor, Windsurf, Claude Code CLI

Installation & Configuration

Claude Code CLI (Easiest):

claude mcp add --transport http figma https://mcp.figma.com/mcp

VS Code (settings.json):

{
  "mcp.servers": {
    "figma-remote": {
      "type": "streamableHttp",
      "url": "https://mcp.figma.com/mcp"
    }
  }
}
json

Cursor (settings):

{
  "mcpServers": {
    "figma": {
      "url": "https://mcp.figma.com/mcp"
    }
  }
}
json

Quick tip:

For detailed setup instructions and authentication, see the official documentation at developers.figma.com/docs/figma-mcp-server/

Note on Claude Desktop:

The official Figma MCP server uses HTTP/SSE transport and currently does not support Claude Desktop, which requires stdio transport. For design system exposure in Claude Desktop, see Approach 2 below.

Approach 2: Custom Design System MCP Server

While Figma's MCP server pulls FROM Figma, you also need to expose your design system's rules, patterns, and guidelines TO the LLM. This is where a custom MCP server comes in.

What This Gives You:

  • Expose your design system context (brand, principles, guidelines)
  • Provide design tokens in LLM-friendly format
  • Share component templates and boilerplates
  • Include accessibility guidelines and checklists
  • Tools for generating components, tokens, and auditing code

Creating Your Custom MCP Server

This project includes a code generator that creates a custom MCP server for your design system. The generated server uses stdio transport and works with Claude Desktop.

// Generated server structure:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

// Exposes resources like:
// - design-system://context (overview, brand, principles)
// - design-system://tokens (all design tokens)
// - design-system://component-template (React boilerplate)
// - design-system://accessibility (WCAG guidelines)

// Provides tools like:
// - generate_component (create new components)
// - generate_design_tokens (export to CSS/Tailwind/TypeScript)
// - audit_accessibility (check WCAG compliance)
// - add_component_variant (extend existing components)
typescript

Installation for Claude Desktop

After generating your MCP server, edit your Claude Desktop config file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "my-design-system": {
      "command": "node",
      "args": [
        "/absolute/path/to/your-mcp-server/dist/index.js"
      ],
      "env": {}
    }
  }
}
json

Quick tip:

Use the Design System Builder tool in this project to generate your custom MCP server. It will create package.json, TypeScript source, Claude Desktop config, and a README with full instructions.

Using Both Approaches Together (Recommended)

The most powerful workflow uses BOTH MCP servers:

  • 1.Figma's MCP Server → Pulls design data (variables, components, frames)
  • 2.Your Custom MCP Server → Provides design system rules and patterns
  • 3.LLM combines both → Generates code that follows your system AND matches Figma designs
Example workflow:
1. "Pull the button component from Figma file xyz"
   → Figma MCP server fetches the design

2. "Generate React code following HypnoLabs design system patterns"
   → Custom MCP server provides templates and guidelines

3. LLM combines both → Generates code matching Figma design + your patterns

Phase 6: CSS Global System

Transform your Figma tokens into CSS variables for use in your codebase. This creates a single source of truth between design and code.

Converting Tokens to CSS Variables

:root {
  /* Primitive Colors */
  --color-blue-50: #eff6ff;
  --color-blue-500: #3b82f6;
  --color-blue-900: #1e3a8a;

  /* Semantic Colors */
  --background-primary: var(--color-gray-50);
  --text-primary: var(--color-gray-900);

  /* Component Tokens */
  --button-bg-primary: var(--color-blue-500);
  --button-text-primary: var(--color-white);

  /* Spacing Scale */
  --spacing-xs: 0.25rem; /* 4px */
  --spacing-sm: 0.5rem;  /* 8px */
  --spacing-md: 1rem;    /* 16px */
}

/* Dark Mode */
[data-theme="dark"] {
  --background-primary: var(--color-gray-900);
  --text-primary: var(--color-gray-50);
}
css

Phase 7: Prompt Engineering for LLM Structuring

Effective prompts help LLMs understand and work with your design system correctly.

System Prompt Template

You are a design system expert helping to structure and implement a design system.

DESIGN SYSTEM CONTEXT:
- Name: [System Name]
- Version: [Version]
- Platforms: [Web, iOS, Android]

TOKEN HIERARCHY:
1. Primitive tokens: Raw values (colors, sizes)
2. Semantic tokens: Purpose-based aliases
3. Component tokens: Component-specific values

RULES:
1. Always use tokens, never hardcode values
2. Reference semantic tokens, not primitive ones
3. Maintain 4.5:1 contrast for normal text
4. Touch targets must be at least 44x44px

Phase 8: Advanced Workflows

Automate synchronization between Figma and your codebase for seamless updates.

Version Control for Design Tokens

Design tokens should be version controlled alongside your code to maintain consistency and enable rollbacks.

Recommended Directory Structure

your-project/
├── design-tokens/
│   ├── figma-export/           # Raw export from Figma
│   │   └── tokens.json         # DTCG JSON from Figma Variables
│   ├── processed/              # Transformed tokens
│   │   ├── tokens.css          # CSS custom properties
│   │   ├── tokens.scss         # Sass variables
│   │   ├── tokens.ts           # TypeScript constants
│   │   └── tailwind.config.js  # Tailwind theme extension
│   └── README.md               # Documentation on token usage
├── src/
└── package.json

Git Workflow for Token Updates

# Step 1: Export from Figma
# File → Variables → Export variables → Save as design-tokens/figma-export/tokens.json

# Step 2: Transform tokens
npm run tokens:transform

# Step 3: Review changes
git diff design-tokens/

# Step 4: Commit with descriptive message
git add design-tokens/
git commit -m "design-tokens: update primary blue shade (500 → 600)

- Adjusted primary blue from #3b82f6 to #2563eb
- Improves contrast ratio from 4.2:1 to 5.1:1 (WCAG AA compliant)
- Affects: buttons, links, focus states"

# Step 5: Create pull request for review
git push origin feature/update-primary-color
gh pr create --title "Update primary color for better accessibility"

Token Versioning Strategy

Use semantic versioning for design token releases:

  • MAJOR (1.0.0): Breaking changes (renamed tokens, removed tokens)
  • MINOR (0.1.0): New tokens added (backwards compatible)
  • PATCH (0.0.1): Token value adjustments (no API changes)
// package.json
{
  "name": "@your-company/design-tokens",
  "version": "2.1.3",
  "description": "Design tokens for Your Company design system",
  "main": "processed/tokens.js",
  "exports": {
    "./css": "./processed/tokens.css",
    "./scss": "./processed/tokens.scss",
    "./tailwind": "./processed/tailwind.config.js"
  }
}
json

Changelog Best Practices

Maintain a CHANGELOG.md to track token changes:

# Changelog

## [2.1.3] - 2025-11-26

### Changed
- `primitive.color.blue.500`: #3b82f6 → #2563eb (improved contrast)
- `semantic.text.link`: Now uses blue.600 instead of blue.500

### Impact
- Affects all link colors and primary buttons
- WCAG AA compliant (5.1:1 contrast on white)

## [2.1.2] - 2025-11-20

### Added
- `semantic.border.focus`: New token for focus outlines
- `component.input.border.focus`: Uses semantic.border.focus

### Fixed
- `semantic.background.danger`: Fixed incorrect reference to red.100
markdown

Pro tip:

Set up a GitHub Action or CI pipeline that automatically validates token JSON structure, checks for broken references, and runs contrast audits on token changes. This catches errors before they reach production.

Continuous Sync Workflow

{
  "scripts": {
    "tokens:export": "# Manual: Export from Figma to design-tokens/figma-export/tokens.json",
    "tokens:transform": "node scripts/transform-tokens.js",
    "tokens:validate": "node scripts/validate-tokens.js",
    "tokens:sync": "npm run tokens:validate && npm run tokens:transform",
    "sync:components": "figma-code-connect sync",
    "sync:all": "npm run tokens:sync && npm run sync:components"
  }
}
json

Automated Figma Sync (Advanced)

For teams with frequent token updates, automate the export process:

// scripts/sync-figma-tokens.js
import { figmaAPI } from './figma-api.js';

async function syncTokens() {
  // 1. Fetch variables from Figma API
  const variables = await figmaAPI.getVariables(fileId);

  // 2. Transform to DTCG format
  const tokens = transformToD TCG(variables);

  // 3. Write to file
  await fs.writeFile('design-tokens/figma-export/tokens.json',
                     JSON.stringify(tokens, null, 2));

  // 4. Run transformation
  await exec('npm run tokens:transform');

  console.log('Tokens synced successfully!');
}

syncTokens();
javascript
# .github/workflows/sync-tokens.yml
name: Sync Design Tokens

on:
  schedule:
    - cron: '0 9 * * 1' # Every Monday at 9am
  workflow_dispatch: # Manual trigger

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Sync tokens from Figma
        run: npm run sync:figma
        env:
          FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
      - name: Create PR if changes detected
        run: |
          if [[ `git status --porcelain` ]]; then
            gh pr create --title "chore: sync design tokens from Figma" \
                        --body "Automated token sync"
          fi
yaml

Phase 8.5: Code to Figma Workflow

While Figma-first workflows are ideal, sometimes you need to go the opposite direction: extracting design patterns from existing code and documenting them in Figma. This reverse workflow is valuable for teams migrating to design systems or documenting legacy codebases.

When to Use Code → Figma

  • Existing production codebase lacks design documentation
  • Engineering-led project needs design system retroactively
  • Migrating from another design tool to Figma
  • Component library exists but design specs are scattered

Scenario 1: Mature Design System → Figma

If you already have a structured design token system (CSS variables, Sass variables, Style Dictionary, etc.), you can export these tokens and push them to Figma as Variables.

Principles: Token Export Pipeline

The general flow is: Code Tokens → DTCG JSON → Figma API → Figma Variables

  1. 1.Extract: Convert your existing tokens to DTCG (Design Tokens Community Group) format
  2. 2.Transform: Map token types to Figma Variable types (color, number, string)
  3. 3.Upload: Use Figma REST API to create/update Variables
  4. 4.Validate: Verify tokens appear correctly in Figma

Traditional Approach: Style Dictionary + Figma API

Style Dictionary can transform your tokens and export them to Figma-compatible JSON:

// style-dictionary.config.js
module.exports = {
  source: ['tokens/**/*.json'],
  platforms: {
    figma: {
      transformGroup: 'js',
      buildPath: 'build/figma/',
      files: [{
        destination: 'tokens.json',
        format: 'json/nested',
        filter: (token) => {
          // Only export color and dimension tokens
          return ['color', 'dimension', 'fontFamily'].includes(token.type);
        }
      }]
    }
  }
};

// Then transform to DTCG format for Figma
npm run tokens:build
node scripts/upload-to-figma.js
javascript

Example upload script using Figma REST API:

// scripts/upload-to-figma.js
const fs = require('fs');
const fetch = require('node-fetch');

const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
const FILE_KEY = process.env.FIGMA_FILE_KEY;

async function uploadTokensToFigma() {
  const tokens = JSON.parse(fs.readFileSync('build/figma/tokens.json', 'utf8'));

  // Transform tokens to Figma Variables format
  const variables = Object.entries(tokens.color).map(([name, value]) => ({
    name: `color/${name}`,
    resolvedType: 'COLOR',
    valuesByMode: {
      [modeId]: rgbaToFigmaColor(value)
    }
  }));

  // POST to Figma API
  const response = await fetch(
    `https://api.figma.com/v1/files/${FILE_KEY}/variables`,
    {
      method: 'POST',
      headers: {
        'X-Figma-Token': FIGMA_TOKEN,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ variables })
    }
  );

  console.log('Tokens uploaded:', await response.json());
}

uploadTokensToFigma();
javascript

Pro Tip: Token Studio for Figma

The Token Studio plugin provides a GUI for importing JSON tokens directly into Figma without writing API scripts. It supports DTCG format, token aliasing, and bidirectional sync.

LLM-Assisted Approach: Token Audit & Validation

Use LLMs to analyze your token structure before uploading to Figma:

PROMPT: Token Structure Audit

I have the following design token structure exported from my codebase:

[Paste tokens.json here]

Please analyze:
1. Are token names semantic and consistent?
2. Do I have proper primitive → semantic → component hierarchy?
3. Are there any missing token types I should add before importing to Figma?
4. Are color values using accessible contrast ratios?
5. Suggest improvements for Figma Variable organization (collections, modes)

Format your response as:
- Issues Found: [list]
- Recommendations: [list]
- Suggested Figma Collections: [list]

Scenario 2: Code-First Projects → New Figma System

When you have an existing codebase without an explicit design system, you need to extract implicit design patterns first, then document them in Figma.

Principles: Pattern Extraction

  1. 1.Inventory: Scan codebase for colors, spacing, typography, shadows
  2. 2.Normalize: Group similar values (e.g., #333, #323232 → gray-900)
  3. 3.Name: Create semantic names based on usage patterns
  4. 4.Structure: Build token hierarchy from extracted patterns
  5. 5.Import: Create Figma Variables from structured tokens

Traditional Approach: Manual Analysis + Scripts

Write scripts to scan your codebase for design values:

// scripts/extract-colors.js
const fs = require('fs');
const glob = require('glob');

// Regex patterns for common color formats
const colorPatterns = [
  /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g,              // Hex
  /rgba?\([^)]+\)/g,                                // RGB/RGBA
  /hsl\([^)]+\)/g,                                  // HSL
];

const colorInventory = new Map();

// Scan all CSS/JS/JSX files
glob.sync('src/**/*.{css,scss,js,jsx,tsx}').forEach(file => {
  const content = fs.readFileSync(file, 'utf8');

  colorPatterns.forEach(pattern => {
    const matches = content.match(pattern) || [];
    matches.forEach(color => {
      const normalized = normalizeColor(color);
      colorInventory.set(
        normalized,
        (colorInventory.get(normalized) || 0) + 1
      );
    });
  });
});

// Sort by frequency
const sortedColors = [...colorInventory.entries()]
  .sort((a, b) => b[1] - a[1])
  .map(([color, count]) => ({ color, count }));

fs.writeFileSync(
  'design-audit/colors.json',
  JSON.stringify(sortedColors, null, 2)
);

console.log(`Found ${sortedColors.length} unique colors`);
javascript

LLM-Assisted Approach: Codebase Analysis

LLMs excel at analyzing unstructured code and identifying patterns:

PROMPT: Design Pattern Extraction

I need to extract an implicit design system from an existing React codebase.

Here are the CSS files and component files:

[Attach or paste key style files]

Please analyze and:

1. **Color Inventory:**
   - List all unique colors used
   - Group similar colors (e.g., shades of blue)
   - Suggest semantic naming (primary, secondary, accent, etc.)
   - Recommend which to keep vs. consolidate

2. **Spacing Patterns:**
   - Identify all margin/padding values used
   - Suggest a consistent spacing scale (4px, 8px, 16px, etc.)
   - Map existing values to suggested scale

3. **Typography:**
   - List font families, sizes, weights, line heights
   - Suggest a type scale and hierarchy

4. **Shadows & Effects:**
   - Extract box-shadow values
   - Suggest elevation scale (sm, md, lg, xl)

5. **Output Format:**
   - Provide DTCG JSON format suitable for importing to Figma
   - Include collections structure for Figma Variables

Example output format:
```json
{
  "color": {
    "primitive": {
      "blue": {
        "500": { "value": "#3b82f6", "type": "color" }
      }
    },
    "semantic": {
      "primary": { "value": "{color.primitive.blue.500}", "type": "color" }
    }
  }
}
```

Quick Tip: Use MCP for Deep Analysis

Create a custom MCP server that gives LLMs direct access to your codebase for more thorough analysis:

// Custom MCP tool: analyze-design-patterns
{
  name: "analyze_design_patterns",
  description: "Scan codebase for implicit design tokens",
  inputSchema: {
    type: "object",
    properties: {
      directory: { type: "string" },
      fileTypes: { type: "array", items: { type: "string" } }
    }
  }
}
typescript

The LLM can then call this tool to analyze your entire codebase programmatically.

Scenario 3: Component Library → Figma Components

Documenting existing React/Vue/Svelte components in Figma creates a single source of truth for both designers and developers. This is especially valuable for component libraries and design systems.

Principles: Component Documentation Strategy

  • Props → Variants: Map component props to Figma component properties
  • States → Variants: Hover, active, disabled states as Figma variants
  • Composition: Nested components should match code hierarchy
  • Documentation: Add descriptions matching JSDoc/TSDoc comments

Traditional Approach: Manual Recreation with Guidelines

Create documentation to guide designers in recreating components accurately:

# Button Component Documentation

## React Implementation
```tsx
<Button
  variant="primary" | "secondary" | "ghost"
  size="sm" | "md" | "lg"
  disabled={boolean}
  leftIcon={ReactNode}
  rightIcon={ReactNode}
>
  Button Text
</Button>
```

## Figma Recreation Guidelines

1. **Create Component Set:**
   - Name: "Button"
   - Variants: variant, size, state

2. **Variant Properties:**
   - variant: primary, secondary, ghost
   - size: sm (32px), md (40px), lg (48px)
   - state: default, hover, active, disabled

3. **Tokens to Use:**
   - Background: {button.background.[variant]}
   - Text: {button.text.[variant]}
   - Border: {button.border.[variant]}
   - Padding horizontal: {button.padding.x.[size]}
   - Padding vertical: {button.padding.y.[size]}

4. **States:**
   - Hover: Reduce opacity to 90%
   - Active: Darken background by 10%
   - Disabled: 50% opacity, cursor not-allowed
markdown

LLM-Assisted Approach: Component Spec Generation

PROMPT: Generate Figma Component Spec

I have the following React component:

[Paste component code]

Please generate a detailed Figma component specification including:

1. **Component Properties:**
   - Map React props to Figma component properties
   - Define variant sets (what should be variants vs. separate components)
   - Specify property types (variant, boolean, instance swap, text)

2. **Visual Specifications:**
   - Dimensions for each size variant
   - Spacing (padding, gap)
   - Typography settings
   - Color tokens to use
   - Border radius, shadows, etc.

3. **Interactive States:**
   - Default, hover, active, focus, disabled states
   - Specify visual changes for each state

4. **Component Hierarchy:**
   - Break down nested component structure
   - Define Auto Layout settings (direction, spacing, alignment)

5. **Design Tokens Reference:**
   - List which design tokens should be used
   - Create token mapping table

Format as a structured Figma component creation guide.

Note: html-to-figma Plugin

The html-to-figma plugin can import rendered HTML/CSS directly into Figma. While not perfect, it's a good starting point for complex components. You'll still need to clean up the result and apply proper tokens.

Scenario 4: Bidirectional Sync Workflows

The ultimate goal: keep code and Figma in sync automatically, regardless of where changes originate.

Principles: Establishing Source of Truth

Key Distinction: Source of Truth

You must establish a clear source of truth for each token type:

  • Figma as Source: Design tokens, colors, spacing, typography (design decisions)
  • Code as Source: Computed values, responsive breakpoints, theme modes (engineering decisions)
  • Bidirectional: Component documentation, specs (collaborative decisions)

Traditional Approach: Git-Based Workflows

# Bidirectional Sync Architecture

┌─────────────────────────────────────────────────────────────┐
│                         Git Repository                      │
│                                                             │
│  ┌─────────────────┐              ┌──────────────────┐    │
│  │ design-tokens/  │              │ figma-sync/      │    │
│  │   - primitive/  │◄────sync────►│   - last-sync/   │    │
│  │   - semantic/   │              │   - conflicts/   │    │
│  │   - component/  │              └──────────────────┘    │
│  └─────────────────┘                                       │
└──────────▲──────────────────────────────────▼──────────────┘
           │                                  │
     [Figma Export]                    [Figma Import]
           │                                  │
    ┌──────┴──────────────────────────────────┴──────┐
    │              Figma File                        │
    │  Design Variables → Code Tokens (Export)       │
    │  Code Tokens → Design Variables (Import)       │
    └───────────────────────────────────────────────┘

**Workflow:**
1. Changes in Figma trigger webhook → export tokens → PR
2. Changes in code → transform tokens → upload to Figma → notify team
3. Conflicts → manual review → resolve → sync

Example GitHub Action for bidirectional sync:

# .github/workflows/design-tokens-sync.yml
name: Design Tokens Bidirectional Sync

on:
  push:
    paths:
      - 'design-tokens/**'
  repository_dispatch:
    types: [figma-webhook]

jobs:
  sync-to-figma:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Transform tokens
        run: npm run tokens:build
      - name: Upload to Figma
        run: node scripts/upload-to-figma.js
        env:
          FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
      - name: Post Slack notification
        run: |
          curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
            -d '{"text":"Design tokens synced to Figma ✅"}'

  sync-from-figma:
    if: github.event_name == 'repository_dispatch'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Export from Figma
        run: node scripts/export-from-figma.js
        env:
          FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
      - name: Check for conflicts
        id: conflict-check
        run: node scripts/check-conflicts.js
      - name: Create PR or Auto-merge
        run: |
          if [ "${{ steps.conflict-check.outputs.has-conflicts }}" == "true" ]; then
            gh pr create --title "🔀 Figma sync (conflicts)" \
                        --body "Conflicts detected - manual review required"
          else
            git commit -am "chore: sync from Figma"
            git push
          fi
yaml

LLM-Assisted Approach: Conflict Resolution

PROMPT: Design Token Conflict Resolution

I have conflicting changes to the same design token:

**Figma Version (designer changed):**
```json
{
  "color/primary": {
    "value": "#2563eb",
    "type": "color",
    "description": "Updated to meet WCAG AA contrast"
  }
}
```

**Code Version (engineer changed):**
```json
{
  "color/primary": {
    "value": "#3b82f6",
    "type": "color",
    "description": "Matches brand guidelines v2.1"
  }
}
```

**Context:**
- Last sync was 3 days ago
- Figma change: contrast accessibility fix
- Code change: brand update

Please:
1. Analyze the conflict reason
2. Recommend which version to keep (or if we need a new value)
3. Suggest communication to team
4. Provide updated token with combined context

Consider:
- Accessibility requirements (WCAG AA)
- Brand consistency
- Breaking changes to existing components
- User impact

Pro Tip: Conflict Prevention

Prevent conflicts by establishing clear ownership rules:

  • Primitive tokens: Figma owns (colors, base spacing)
  • Semantic tokens: Joint ownership (sync bidirectionally)
  • Component tokens: Code owns (computed values)
  • Add CODEOWNERS file to design-tokens/ directory

Practical Implementation Guide

Figma REST API Essentials

Key endpoints for Code → Figma workflows:

// 1. Create Variables (bulk)
POST https://api.figma.com/v1/files/{file_key}/variables/batch

{
  "variableCollections": [{
    "name": "Primitives",
    "modes": [{ "name": "Light" }, { "name": "Dark" }]
  }],
  "variables": [{
    "name": "color/blue/500",
    "resolvedType": "COLOR",
    "variableCollectionId": "{collection_id}",
    "valuesByMode": {
      "{mode_id}": { r: 0.231, g: 0.51, b: 0.965, a: 1 }
    }
  }]
}

// 2. Update Existing Variables
PUT https://api.figma.com/v1/files/{file_key}/variables/{variable_id}

{
  "valuesByMode": {
    "{mode_id}": { r: 0.145, g: 0.227, b: 0.925, a: 1 }
  }
}

// 3. Get All Variables (for sync comparison)
GET https://api.figma.com/v1/files/{file_key}/variables/local
javascript

Example: Complete Token Upload Script

// upload-tokens-to-figma.ts
import fs from 'fs';

interface Token {
  value: string;
  type: 'color' | 'dimension' | 'fontFamily';
  description?: string;
}

interface TokenCollection {
  [category: string]: {
    [token: string]: Token;
  };
}

async function uploadTokensToFigma(
  tokens: TokenCollection,
  fileKey: string,
  accessToken: string
) {
  const baseUrl = 'https://api.figma.com/v1';

  // Step 1: Get or create Variable Collection
  const collectionsRes = await fetch(
    `${baseUrl}/files/${fileKey}/variables/local`,
    { headers: { 'X-Figma-Token': accessToken } }
  );
  const { meta } = await collectionsRes.json();

  let collectionId = meta.variableCollections.find(
    (c: any) => c.name === 'Design Tokens'
  )?.id;

  if (!collectionId) {
    // Create collection
    const createRes = await fetch(
      `${baseUrl}/files/${fileKey}/variables/batch`,
      {
        method: 'POST',
        headers: {
          'X-Figma-Token': accessToken,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          variableCollections: [{
            name: 'Design Tokens',
            modes: [{ name: 'Light' }]
          }]
        })
      }
    );
    const created = await createRes.json();
    collectionId = created.variableCollections[0].id;
  }

  // Step 2: Transform tokens to Figma format
  const variables = [];
  const modeId = meta.variableCollections
    .find((c: any) => c.id === collectionId)
    .modes[0].modeId;

  for (const [category, categoryTokens] of Object.entries(tokens)) {
    for (const [name, token] of Object.entries(categoryTokens)) {
      variables.push({
        name: `${category}/${name}`,
        resolvedType: mapTypeToFigma(token.type),
        variableCollectionId: collectionId,
        valuesByMode: {
          [modeId]: transformValue(token.value, token.type)
        },
        description: token.description || ''
      });
    }
  }

  // Step 3: Upload in batches (Figma has rate limits)
  const BATCH_SIZE = 50;
  for (let i = 0; i < variables.length; i += BATCH_SIZE) {
    const batch = variables.slice(i, i + BATCH_SIZE);

    await fetch(`${baseUrl}/files/${fileKey}/variables/batch`, {
      method: 'POST',
      headers: {
        'X-Figma-Token': accessToken,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ variables: batch })
    });

    console.log(`Uploaded batch ${i / BATCH_SIZE + 1}`);

    // Rate limit: wait 1 second between batches
    await new Promise(resolve => setTimeout(resolve, 1000));
  }

  console.log('✅ All tokens uploaded to Figma');
}

function mapTypeToFigma(type: string): string {
  const mapping: Record<string, string> = {
    'color': 'COLOR',
    'dimension': 'FLOAT',
    'fontFamily': 'STRING'
  };
  return mapping[type] || 'STRING';
}

function transformValue(value: string, type: string): any {
  if (type === 'color') {
    // Convert hex to RGBA object
    const hex = value.replace('#', '');
    const r = parseInt(hex.substr(0, 2), 16) / 255;
    const g = parseInt(hex.substr(2, 2), 16) / 255;
    const b = parseInt(hex.substr(4, 2), 16) / 255;
    return { r, g, b, a: 1 };
  }

  if (type === 'dimension') {
    // Convert rem/px to number
    return parseFloat(value);
  }

  return value;
}

// Usage
const tokens = JSON.parse(
  fs.readFileSync('design-tokens/tokens.json', 'utf8')
);

uploadTokensToFigma(
  tokens,
  process.env.FIGMA_FILE_KEY!,
  process.env.FIGMA_TOKEN!
);
typescript

MCP Server Concepts for Code → Figma

Create custom MCP tools to expose code analysis to LLMs:

// Example MCP server tools for design system analysis

{
  "tools": [
    {
      "name": "extract_design_tokens",
      "description": "Scan codebase for implicit design tokens",
      "inputSchema": {
        "type": "object",
        "properties": {
          "directory": {
            "type": "string",
            "description": "Root directory to scan"
          },
          "tokenTypes": {
            "type": "array",
            "items": { "enum": ["color", "spacing", "typography", "shadow"] }
          }
        }
      }
    },
    {
      "name": "analyze_component_props",
      "description": "Extract component API from TypeScript definitions",
      "inputSchema": {
        "type": "object",
        "properties": {
          "componentPath": {
            "type": "string",
            "description": "Path to component file"
          }
        }
      }
    },
    {
      "name": "upload_tokens_to_figma",
      "description": "Upload extracted tokens to Figma Variables",
      "inputSchema": {
        "type": "object",
        "properties": {
          "tokens": {
            "type": "object",
            "description": "DTCG formatted tokens"
          },
          "figmaFileKey": { "type": "string" }
        }
      }
    }
  ]
}
typescript

With these MCP tools available, an LLM can orchestrate the entire Code → Figma workflow:

PROMPT: Code to Figma Workflow

Please analyze my React component library and create a Figma design system:

1. Use extract_design_tokens to scan ./src/components for colors, spacing, typography
2. Analyze the extracted tokens and normalize similar values
3. Create a proper token hierarchy (primitive → semantic → component)
4. Use analyze_component_props on key components (Button, Input, Card)
5. Generate Figma component specs for each component
6. Use upload_tokens_to_figma to push the structured tokens to Figma file: {file_key}

Provide a summary report of:
- How many tokens were extracted and consolidated
- Which components were analyzed
- Recommendations for design system improvements

Pro Tip: Incremental Migration

Don't try to migrate everything at once. Start with:

  1. 1.Colors (easiest to extract and most impactful)
  2. 2.Spacing and typography (clear patterns)
  3. 3.Core components (Button, Input, Card)
  4. 4.Complex components and compositions

Each phase can be deployed independently, making the migration less risky.

Recommended Tools Summary

ToolPurposeBest For
Style DictionaryTransform tokens between formatsExisting design systems with structured tokens
Token StudioBidirectional sync, GUI for tokensTeams wanting no-code token management
html-to-figmaImport rendered HTML to FigmaQuick component documentation, starting point
Figma REST APIProgrammatic Figma accessCustom automation, CI/CD integration
LLM + MCPIntelligent analysis, pattern extractionLegacy codebases without explicit design systems

Why This Matters

Historically, design systems flowed one direction: Figma → Code. But modern workflows are more nuanced. Sometimes code leads (especially in engineering-heavy orgs), sometimes design leads, and often both evolve simultaneously. Supporting bidirectional workflows ensures your design system stays synchronized regardless of where changes originate.

Phase 9: Best Practices & Tips

Token Naming Best Practices

DO:

  • Use clear, descriptive names: semantic/text/primary
  • Follow consistent hierarchy: category/subcategory/name/variant
  • Use purpose-based semantic names: semantic/background/danger

DON'T:

  • Use presentational names: text/dark-gray
  • Skip semantic layer: primitive → component directly
  • Use abbreviations that aren't universal: btn/bg/prim

Phase 10: Troubleshooting & Common Issues

Issue 1: Token References Breaking

Problem: Variables reference each other incorrectly or show "Unresolved" in Figma

Error in Figma:
semantic/text/primary → {primitive.color.gray.900}
❌ Shows "Unresolved" badge

Common causes:
1. Typo in reference path
2. Referenced token doesn't exist
3. Referenced token is in different collection
4. Circular reference loop

Solutions:

  • Check path syntax: Use absolute references like {primitive.color.blue.500}
  • Verify token exists: Search in Variables panel to confirm the token is created
  • Check collection scope: Ensure both tokens are in same or accessible collections
  • Avoid circular refs: Don't create A → B → A loops
  • Document dependencies: Keep a visual map of token hierarchy

Issue 2: Figma Export Contains Invalid JSON

Problem: Exported JSON file won't parse or has errors

Common issues:
❌ Missing closing braces
❌ Trailing commas
❌ Invalid escape characters in token names
❌ Special characters in values

Solutions:

  • Validate JSON: Use jsonlint.com or `jq` command to check validity
  • Check token names: Avoid special characters like quotes, backslashes
  • Re-export: Sometimes Figma export can be corrupted - try again
  • Use validation script: Add JSON schema validation to your pipeline

Issue 3: Colors Look Different in Code vs Figma

Problem: Colors appear different when applied in browser/code

Possible causes:
1. Color space mismatch (sRGB vs Display P3)
2. Gamma correction differences
3. Browser color profile settings
4. Monitor calibration differences
5. Dark mode/light mode context

Solutions:

  • Use sRGB in Figma: Document Settings → Color profile → sRGB
  • Export as hex: Avoid RGB() format which can have rounding issues
  • Test in target browser: Always verify colors in actual environment
  • Use color picker: Sample actual rendered color to confirm match

Issue 4: MCP Server Not Connecting

Problem: MCP server won't connect or times out

Error messages:
"Failed to connect to MCP server"
"Connection timeout"
"Server not responding"

Solutions for Official Figma MCP:

  • Check internet: Remote server requires connection
  • Verify URL: Ensure `https://mcp.figma.com/mcp` is correct
  • For desktop server: Confirm Figma Desktop app is running
  • Check firewall: Ensure port 3845 is not blocked (desktop server)

Solutions for Custom MCP Server:

  • Check paths: Verify absolute path to dist/index.js is correct
  • Build server: Run `npm run build` to compile TypeScript
  • Check permissions: Ensure file is executable (chmod +x)
  • Test manually: Run `node /path/to/dist/index.js` to see errors
  • Restart Claude Desktop: Reload config after changes

Issue 5: Inconsistent LLM Outputs

Problem: LLM generates code that doesn't follow design system rules

Example bad output:
// LLM hardcodes colors instead of using tokens
const Button = () => (
  <button style={{ background: '#3B82F6' }}>  // ❌ Hardcoded
    Click me
  </button>
)

// Should be:
const Button = () => (
  <button className="bg-primary">  // ✓ Uses token
    Click me
  </button>
)

Solutions:

  • Use MCP server: Provide design system context via custom MCP server
  • Explicit prompts: Always specify "use design tokens" or "follow HypnoLabs patterns"
  • Provide examples: Show correct token usage in your prompt
  • Add validation: Ask LLM to check its own output against token list
  • Iterative refinement: Review and correct, then ask LLM to learn from corrections

Issue 6: Token Count Explosion

Problem: Design system has too many tokens, becomes unmanageable

Signs of token bloat:
• 500+ tokens in your system
• Multiple similar tokens (blue-light, blue-lighter, blue-lightest, etc.)
• Tokens used only once
• Overlapping semantic tokens

Solutions:

  • Audit usage: Track which tokens are actually used in components
  • Consolidate similar: Merge tokens that differ by tiny amounts
  • Remove unused: Delete tokens that aren't referenced anywhere
  • Stick to scales: Use systematic scales instead of one-off values
  • Regular cleanup: Quarterly token audits to prevent accumulation

Prevention is better than cure:

Set up a token approval process. Before adding new tokens, check if existing ones can be reused. Require justification for why a new token is needed. This prevents token bloat before it starts.

Phase 11: Starting with shadcn/ui and Making It Your Own

shadcn/ui provides production-ready components you can customize to match your design system.

What is shadcn/ui?

A collection of beautifully designed, accessible React components built with Radix UI and Tailwind CSS. Unlike traditional libraries, you copy the source code into your project—you own it completely.

Customization Strategy

Don't: Replace shadcn components entirely

Do: Keep shadcn components, remap their CSS variables to your tokens

:root {
  /* Map your tokens to shadcn variables */
  --primary: 217 91% 60%;        /* Your brand blue in HSL */
  --background: 210 20% 98%;     /* Your background */
  --radius: 0.75rem;             /* Your border radius */
}

.dark {
  --primary: 217 91% 60%;
  --background: 222 47% 11%;
}
css

Quick tip:

Start with shadcn/ui for standard components (buttons, inputs, dialogs) and build custom components for unique brand moments. This gives you speed AND customization.

Phase 12: Testing & Quality Assurance

Testing your design system ensures consistency, accessibility, and reliability across your product.

Visual Regression Testing

Catch unintended visual changes when tokens or components are updated.

// Example with Chromatic or Percy
import { render } from '@testing-library/react';
import { Button } from '@/components/ui/button';

describe('Button Visual Tests', () => {
  it('matches snapshot', () => {
    const { container } = render(
      <>
        <Button variant="primary">Primary</Button>
        <Button variant="secondary">Secondary</Button>
        <Button variant="ghost">Ghost</Button>
        <Button variant="primary" disabled>Disabled</Button>
      </>
    );
    expect(container).toMatchSnapshot();
  });
});
javascript

Accessibility Testing

Ensure your design system meets WCAG standards.

Automated Accessibility Checks

// Using jest-axe and Testing Library
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { Button } from '@/components/ui/button';

expect.extend(toHaveNoViolations);

describe('Button Accessibility', () => {
  it('should not have accessibility violations', async () => {
    const { container } = render(
      <Button>Click me</Button>
    );
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });

  it('has proper ARIA attributes', () => {
    const { getByRole } = render(<Button>Submit</Button>);
    const button = getByRole('button', { name: 'Submit' });
    expect(button).toBeInTheDocument();
  });
});
javascript

Color Contrast Testing

// Check contrast ratios for all color combinations
import { getContrastRatio } from '@/lib/color-utils';

describe('Token Contrast Tests', () => {
  it('primary text on white meets WCAG AA', () => {
    const ratio = getContrastRatio('#1F2937', '#FFFFFF');
    expect(ratio).toBeGreaterThanOrEqual(4.5); // WCAG AA
  });

  it('primary button has sufficient contrast', () => {
    const bgColor = '#3B82F6'; // semantic.action.primary
    const textColor = '#FFFFFF'; // semantic.text.inverse
    const ratio = getContrastRatio(bgColor, textColor);
    expect(ratio).toBeGreaterThanOrEqual(4.5);
  });
});
javascript

Component API Testing

Test that components accept correct props and behave as expected.

import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '@/components/ui/button';

describe('Button Component', () => {
  it('renders with correct variant classes', () => {
    render(<Button variant="primary">Text</Button>);
    const button = screen.getByRole('button');
    expect(button).toHaveClass('bg-primary');
  });

  it('calls onClick handler when clicked', () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click</Button>);
    fireEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when disabled prop is true', () => {
    render(<Button disabled>Disabled</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});
javascript

Design Token Validation

Validate token structure and relationships programmatically.

// Token validation script
import tokens from './design-tokens/figma-export/tokens.json';

describe('Design Token Tests', () => {
  it('all token references are valid', () => {
    const validateReferences = (obj, path = '') => {
      for (const [key, value] of Object.entries(obj)) {
        const currentPath = path ? `${path}.${key}` : key;

        if (value.$value && typeof value.$value === 'string') {
          // Check if it's a reference
          if (value.$value.startsWith('{') && value.$value.endsWith('}')) {
            const refPath = value.$value.slice(1, -1);
            const referenced = getNestedToken(tokens, refPath);
            expect(referenced).toBeDefined(
              `Token ${currentPath} references non-existent ${refPath}`
            );
          }
        } else if (typeof value === 'object') {
          validateReferences(value, currentPath);
        }
      }
    };

    validateReferences(tokens);
  });

  it('no circular references exist', () => {
    const checkCircular = (tokenPath, visited = new Set()) => {
      if (visited.has(tokenPath)) {
        throw new Error(`Circular reference detected: ${[...visited, tokenPath].join(' → ')}`);
      }

      visited.add(tokenPath);
      const token = getNestedToken(tokens, tokenPath);

      if (token.$value?.startsWith('{')) {
        const refPath = token.$value.slice(1, -1);
        checkCircular(refPath, new Set(visited));
      }
    };

    // Test all tokens
    Object.keys(tokens).forEach(collection => {
      checkCircular(collection);
    });
  });

  it('all colors are valid hex codes', () => {
    const hexRegex = /^#[0-9A-Fa-f]{6}$/;
    // ... check all color tokens match hex format
  });
});
javascript

Manual Testing Checklist

Some things still require human testing:

  • Keyboard navigation: Tab through all interactive elements
  • Screen reader testing: Test with NVDA, JAWS, or VoiceOver
  • Mobile responsiveness: Test on actual devices, not just browser tools
  • Dark mode: Switch themes and verify all components look correct
  • Browser compatibility: Test in Chrome, Firefox, Safari, Edge
  • Zoom levels: Test at 100%, 150%, 200% zoom
  • Print styles: If applicable, test print layouts

Performance Testing

Ensure your design system doesn't impact performance.

// Example performance tests
import { measurePerformance } from './test-utils';

describe('Design System Performance', () => {
  it('CSS bundle size is under 50KB (gzipped)', async () => {
    const bundleSize = await getBundleSize('./dist/tokens.css');
    expect(bundleSize.gzipped).toBeLessThan(50 * 1024);
  });

  it('component library loads in under 200ms', async () => {
    const loadTime = await measurePerformance(() => {
      require('@/components/ui/button');
      require('@/components/ui/input');
      require('@/components/ui/card');
    });
    expect(loadTime).toBeLessThan(200);
  });
});
javascript

CI/CD Integration

Run tests automatically on every commit.

# .github/workflows/design-system-tests.yml
name: Design System Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Run token validation
        run: npm run test:tokens

      - name: Run component tests
        run: npm run test:components

      - name: Run accessibility tests
        run: npm run test:a11y

      - name: Visual regression tests
        run: npm run test:visual
        env:
          CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_TOKEN }}

      - name: Check bundle size
        run: npm run test:size
yaml

Pro tip:

Create a "Design System Health Dashboard" that shows test results, token coverage, accessibility scores, and bundle sizes. This gives stakeholders visibility into system quality and helps catch regressions early.

Quick Reference Checklist

Starting a New Design System

  • Complete visual design audit
  • Create primitive color, spacing, typography scales
  • Set up variable collections in Figma
  • Create semantic token layer
  • Build core components (atoms)
  • Connect variables to components
  • Export tokens to DTCG JSON
  • Set up MCP server for LLM integration
  • Generate CSS variables from tokens
  • Document usage guidelines
  • Test with LLM generation workflows

Congratulations!

You now have a comprehensive understanding of building design systems that integrate seamlessly with LLM workflows. Start small, iterate often, and let automation handle the synchronization between design and code.