Our Figma-to-Code Workflow That Actually Scales
Published
11 min read
Feb 10, 2025

Design

Our Figma-to-Code Workflow That Actually Scales

FigmaDesignWorkflowDesign Systems

Overview

Handoff between design and engineering breaks at scale. Here's the component naming, token structure, and review process we use to keep it seamless.

FigmaDesignWorkflowDesign Systems
Sana Yildiz

Sana Yildiz

Author
11 min read
Reading Time

Our Figma-to-Code Workflow That Actually Scales

The Handoff That Never Works

Designer: "It's all in Figma, just build it" Engineer: "The spacing is inconsistent, the components don't match, and where are the hover states?"

Sound familiar? The gap between design and code is where products go to die. After 50+ projects, we've built a workflow that bridges that gap completely.

Figma to code workflow diagramFigma to code workflow diagram

The Golden Rule: Design Is Code

The most important shift: Treat your Figma file as code. Every color, space, and font should map directly to your codebase's design tokens.

Token Naming Convention

Figma Variable → CSS Custom Property → Tailwind Config ───────────────────────────────────────────────────── color/primary/500 → --color-primary-500 → colors.primary.500 space/400 → --spacing-4 → spacing.4 font/size/heading/1 → --font-size-h1 → fontSize.h1

Phase 1: The Design System Foundation

Colors (The Most Common Failure Point)

In Figma: Create color variables with semantic names:

  • color/primary
  • color/background/base
  • color/text/primary
  • color/border/default

In Code:

css
/* globals.css */
:root {
  --color-primary: #3b82f6;
  --color-background-base: #ffffff;
  --color-text-primary: #111827;
  --color-border-default: #e5e7eb;
}

.dark {
  --color-primary: #60a5fa;
  --color-background-base: #111827;
  --color-text-primary: #f9fafb;
  --color-border-default: #374151;
}
javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: 'var(--color-primary)',
        background: {
          base: 'var(--color-background-base)',
        },
        text: {
          primary: 'var(--color-text-primary)',
        },
        border: {
          default: 'var(--color-border-default)',
        }
      }
    }
  }
}

Color token mapping visualizationColor token mapping visualization

Spacing (The 8px Grid)

In Figma: Create spacing variables:

  • space/100 = 4px
  • space/200 = 8px
  • space/300 = 12px
  • space/400 = 16px
  • space/500 = 24px
  • space/600 = 32px
  • space/800 = 48px
  • space/1000 = 64px

In Code:

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        100: '4px',
        200: '8px',
        300: '12px',
        400: '16px',
        500: '24px',
        600: '32px',
        800: '48px',
        1000: '64px',
      }
    }
  }
}

Typography

In Figma: Create text styles:

  • Heading 1: 32px/40px/700
  • Heading 2: 24px/32px/600
  • Body Large: 18px/28px/400
  • Body Base: 16px/24px/400
  • Caption: 14px/20px/400

In Code:

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontSize: {
        'h1': ['32px', { lineHeight: '40px', fontWeight: '700' }],
        'h2': ['24px', { lineHeight: '32px', fontWeight: '600' }],
        'body-lg': ['18px', { lineHeight: '28px', fontWeight: '400' }],
        'body': ['16px', { lineHeight: '24px', fontWeight: '400' }],
        'caption': ['14px', { lineHeight: '20px', fontWeight: '400' }],
      }
    }
  }
}

Phase 2: Component Library Mapping

The Component Specification Document

For every component in Figma, create a spec:

markdown
# Button Component

## Variants
- primary (blue background, white text)
- secondary (gray background, gray text)
- outline (transparent, blue border)

## Sizes
- sm: 32px height, 12px horizontal padding
- md: 40px height, 16px horizontal padding
- lg: 48px height, 24px horizontal padding

## States
- default
- hover (darken background by 10%)
- active (scale 0.98)
- disabled (50% opacity)

## Figma frame name: Button / [Variant] / [Size]
Example: Button / Primary / MD

The Code Implementation

tsx
// components/ui/Button.tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md font-medium transition-all focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        primary: 'bg-blue-600 text-white hover:bg-blue-700 active:scale-98',
        secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
        outline: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50',
      },
      size: {
        sm: 'h-8 px-3 text-sm',
        md: 'h-10 px-4 text-base',
        lg: 'h-12 px-6 text-lg',
      },
    },
    defaultVariants: {
      variant: 'primary',
      size: 'md',
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

export function Button({ className, variant, size, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}

Component variant mappingComponent variant mapping

Phase 3: The Automation Layer

Figma Tokens Plugin

Export design tokens automatically:

json
// tokens.json (exported from Figma)
{
  "color": {
    "primary": { "value": "#3b82f6" },
    "background": { "base": { "value": "#ffffff" } }
  },
  "spacing": {
    "400": { "value": "16px" }
  }
}

Then transform to Tailwind config:

javascript
// scripts/transform-tokens.js
const tokens = require('./tokens.json')

module.exports = {
  theme: {
    extend: {
      colors: Object.entries(tokens.color).reduce((acc, [key, value]) => {
        acc[key] = value.value
        return acc
      }, {})
    }
  }
}

Storybook Integration

Sync Figma components with Storybook:

tsx
// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'

const meta: Meta<typeof Button> = {
  title: 'UI/Button',
  component: Button,
  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/file/.../Button',
    },
  },
}

export const Primary: StoryObj = {
  args: {
    variant: 'primary',
    children: 'Click me',
  },
}

Phase 4: The Review Process

Before Design Review

Designer checks:

  • All components use established variants (no custom overrides)
  • Spacing follows 8px grid
  • Colors use tokens, not hardcoded hex
  • Text styles use typography scale

Engineer checks:

  • Component props match Figma variants
  • Responsive behavior defined
  • Dark mode considered
  • Accessibility (contrast, focus states)

During Implementation Review

Pair review of a single component:

  1. Designer shares the Figma component frame
  2. Engineer shares the coded component in Storybook
  3. Compare variant by variant:
    • Hover states match?
    • Disabled states match?
    • Spacing matches?
    • Typography matches?
  4. Document discrepancies and fix

Phase 5: The Living Style Guide

Auto-generated Documentation

tsx
// app/style-guide/page.tsx
export default function StyleGuide() {
  return (
    <div>
      <section>
        <h2>Colors</h2>
        <div className="grid grid-cols-4 gap-4">
          {Object.entries(colors).map(([name, value]) => (
            <div key={name} className="space-y-2">
              <div className="h-20 rounded" style={{ backgroundColor: value }} />
              <p>{name}</p>
              <p className="text-sm text-gray-500">{value}</p>
            </div>
          ))}
        </div>
      </section>
      
      <section>
        <h2>Buttons</h2>
        <div className="space-x-4">
          <Button variant="primary">Primary</Button>
          <Button variant="secondary">Secondary</Button>
          <Button variant="outline">Outline</Button>
        </div>
      </section>
    </div>
  )
}

Living style guide screenshotLiving style guide screenshot

The Results (After Implementing This Workflow)

Before:

  • Design-to-code time: 2-3 weeks per page
  • Inconsistencies per review: 15-20
  • Designer/engineer friction: Daily
  • Post-launch design fixes: 2 weeks

After:

  • Design-to-code time: 3-5 days per page
  • Inconsistencies per review: 2-3
  • Designer/engineer friction: Weekly sync only
  • Post-launch design fixes: 2 days

The Checklist for Your Next Project

Before Design

  • Set up design tokens in Figma
  • Create spacing/spacing scale
  • Define typography system
  • Establish component variants

During Design

  • Use only token-based colors
  • Use only spacing scale
  • Create component specs
  • Name layers semantically

During Development

  • Export tokens to code
  • Build component library first
  • Create Storybook stories
  • Document component API

During Review

  • Compare variant by variant
  • Check hover/focus/active states
  • Verify responsive behavior
  • Test dark mode

The secret isn't a tool or plugin — it's shared language and process. When designers think in components and engineers think in design tokens, handoff becomes collaboration. And that's when great products get built.

Sana Yildiz

Written by

Sana Yildiz

Let's work together

Start your project.