Design Engineering
Foundations

Designing for Handoff

Design Figma files that translate cleanly into code — naming conventions, file structure, autolayout rules, and communication patterns for developers and AI agents.

The gap between Figma and code is where projects lose momentum. This page covers what designers can do inside Figma to close it — for both human engineers and AI agents. They need the same things: named layers, token values, autolayout, and every important state shown.

Why handoffs break

Failure modeWhat happensConsequence
Unnamed layersRectangle 47, Group 12 — agent generates div.Rectangle47Garbage component names, missed matches
Arbitrary valuesA hex that differs from the design token by 1%Designer goes "why doesn't it look right?"
Missing statesOnly the happy path is shown at desktop widthLoading, empty, error, mobile all break in production
Broken autolayoutFrames with absolute-positioned childrenCannot translate to flexbox/grid — agent guesses and gets it wrong
No variant structureSix separate button frames instead of one component with variantsAgent creates six separate components, no reuse
Lorem ipsumPlaceholder copy used throughoutReal content breaks layout; nobody caught the 3-line names that overflow

Each of these is preventable by working inside Figma with the code translation in mind from the start.

Figma file structure

Figma file structure

Name pages after routes. This gives agents an immediate map from design to codebase.

Figma → Code mapping
Figma page name          → App Router path
─────────────────────────────────────────────
Dashboard                → app/dashboard/
  Dashboard/Home          → app/dashboard/page.tsx
  Dashboard/Projects      → app/dashboard/projects/page.tsx
Auth                     → app/auth/
  Auth/Login              → app/auth/login/page.tsx
  Auth/SignUp             → app/auth/signup/page.tsx
Settings                 → app/settings/page.tsx

Within a page, group frames into named sections that correspond to layout slots:

Dashboard page
├── Sidebar              → layout sidebar slot
├── Header               → layout header slot
├── Main/ProjectTable    → page content
└── Main/QuickActions    → page content

If your codebase uses route groups like (dashboard), name your Figma pages the same way. The goal is that someone — human or agent — can look at the Figma file and know exactly where every screen lives in the repo.

Layer naming conventions

Every layer name should answer: what component is this in the codebase?

Component names

Use PascalCase matching your component naming convention:

Layer nameMaps to
Button/Primary/Large<Button variant="primary" size="lg">
Card/ProjectSummary<ProjectSummaryCard>
Input/Email<Input type="email">
Table/HeaderRowTable header row component
Badge/Status.Done<Badge status="done">

Grouping with slashes

Forward slashes create collapsible groups in Figma's layer panel and encode the hierarchy:

Page/Dashboard
├── Sidebar/Nav/Logo
├── Sidebar/Nav/Link.Home
├── Sidebar/Nav/Link.Projects
├── Header/SearchInput
├── Header/UserMenu
├── Main/Toolbar
├── Main/Table.Header
└── Main/Table.Row

Do not leave layers named Rectangle 47, Frame 12, or Component 1. Every unnamed layer is a missed opportunity for the agent to understand what it should build. Budget 5-10 minutes per page to clean up layer names before handoff.

Autolayout rules

Auto Layout in Figma translates almost 1:1 to CSS flexbox. Every frame should use Auto Layout unless there is a specific reason not to.

Figma propertyCSS equivalent
Direction (horizontal)flex-direction: row
Direction (vertical)flex-direction: column
Gapgap
Padding (all sides)padding
Horizontal paddingpadding-inline
Vertical paddingpadding-block
Alignment (top/left/center/right/bottom)align-items + justify-content
Space betweenjustify-content: space-between
Hug contentswidth: fit-content / height: fit-content
Fill containerwidth: 100% / height: 100% / flex: 1
Wrapflex-wrap: wrap

What to avoid

  • Absolute positioning — has no clean CSS flexbox equivalent. Use Auto Layout frames instead.
  • Overlapping elements with manual x/y coordinates — translate to relative positioning or z-index with intent.
  • Mixed-direction layouts without wrapping — if content needs to break into rows, use Wrap.
  • Nested Auto Layout frames used as centering hacks — these produce unnecessary nesting in generated code. Use alignment properties instead.

Token-aware design

Design tokens are the single source of truth for colours, spacing, typography, and radii. When designers use tokens instead of raw values, the generated code references the same variable as the codebase. When they use raw values, agents inline hex codes and magic numbers.

Figma variables → CSS custom properties

Create Figma variables that match your CSS custom properties exactly:

Variable naming: Figma ↔ CSS
Figma variable          CSS custom property
─────────────────────────────────────────────
color/primary/500       --color-primary
color/neutral/100       --color-neutral-100
spacing/4               --spacing-4  (1rem)
spacing/8               --spacing-8  (2rem)
radius/md               --radius-md
font/sans               --font-sans

Rules for token usage

  • Bind every colour fill to a Figma variable, never a raw hex
  • Bind every spacing value (gap, padding, margin) to a spacing variable
  • Use text variables for font family, size, weight, and line height
  • If a value does not exist as a token, add the token — do not use a raw value

Tools like Tokens Studio, the Figma Variables API, or CI-driven token sync can keep Figma and code in sync bidirectionally. Start with a manual token audit: export your Figma variables, diff them against your globals.css, and align mismatches. See AI-Ready Design Systems for the schema that agents consume.

Component variants → code props

Figma component variants should map directly to React component props. The cleaner the mapping, the less the agent has to guess.

States as variants

Model every interaction state as a component variant, not as a separate component:

StateVariant valueBecomes prop
Defaultdefaultstate="default"
HoverhoverShown in prototype
Focusfocus:focus-visible styles
Active/pressedactive:active styles
Disableddisableddisabled prop
LoadingloadingisLoading prop

Sizes as a separate axis

Keep size variants on their own property axis so they compose with states:

Button component variants
Property 1: Size  →  sm | md | lg
Property 2: State →  default | hover | focus | active | disabled | loading

This maps to:

<Button size="sm" state="default">Save</Button>
<Button size="lg" disabled>Save</Button>

Agents that see this variant structure generate a single component with props. Agents that see six disconnected button frames generate six separate components.

What agents and developers need

Before handing off a design file, verify that every screen includes:

States

Every screen must show more than the happy path. Include at minimum:

  • Loading — skeleton or spinner for every data-dependent region
  • Empty — what the user sees before data exists
  • Error — API failure, validation error, or permission denied
  • Success — confirmation after completing an action
  • Edge cases — long names, zero results, expired sessions

Real copy

Use the actual text that will appear in the product. Lorem ipsum hides layout problems: names that are 3 lines long, button labels that overflow, headings that wrap at awkward breakpoints.

Breakpoint annotations

Note where the layout changes in frame names or descriptions:

Frame name: "Dashboard/Home [desktop: 1440]"
Frame name: "Dashboard/Home [tablet: 768]"
Frame name: "Dashboard/Home [mobile: 375]"

Dev Mode annotations

Use Figma Dev Mode to annotate:

  • Spacing values between elements
  • Component names matching the codebase
  • Token references for colours and typography
  • Notes about responsive behaviour or interaction details

AI agents that have access to Figma (via MCP or plugins) can read Dev Mode annotations and use them to verify generated code against the design. The more information you encode as structured data rather than visual appearance, the more accurate the agent's output. See Agent Collaboration for prompt templates that reference Figma designs.

Design-to-code tools

Several tools now translate Figma designs directly into code. They are not replacements for design engineering — they are accelerators that handle the mechanical translation so you can focus on the decisions that matter.

Tool comparison

ToolBest forOutputLimitations
Figma Dev ModeInspecting spacing, tokens, and component specsCode snippets (CSS, Tailwind, SwiftUI)Generates snippets, not complete components. Requires manual composition.
Figma-to-Code plugins (Anima, Locofy, Builder.io)Rapid prototyping from high-fidelity mockupsReact/Vue components with stylesOutput quality varies with Figma file discipline. Named layers and autolayout are essential.
v0 / Bolt / LovableGenerating full pages from prompts or screenshotsComplete React + Tailwind componentsDesign fidelity depends on prompt quality. Needs human review for tokens, states, and accessibility.
AI coding agents (Claude, Cursor, Copilot)Implementing components from Figma screenshots or Dev Mode referencesFull component files with logicBest results when Figma file is well-structured (named layers, tokens, autolayout). See Agent Collaboration.

When to use which approach

ScenarioRecommended tool
Quick prototype from a Figma frameFigma-to-Code plugin + manual cleanup
Production component from a specAI coding agent with explicit prompt (states, tokens, accessibility)
Checking spacing and token valuesFigma Dev Mode
Design system component with variantsWrite by hand — generated code rarely handles variant APIs cleanly
Full page with complex layoutAI agent with layout prompt + manual layout shell

Design-to-code tools are only as good as the Figma file they consume. A file with unnamed layers, arbitrary hex values, and no autolayout will produce garbage regardless of the tool. Invest in file structure and naming conventions first — the tools become useful after.

Handoff checklist

Before handing off a Figma file to a developer or agent, confirm:

  • Every layer is named meaningfully — no Rectangle 47, Frame 12, or Component 1
  • Pages are named after routes or route groups
  • All colours come from Figma variables matching CSS tokens
  • All spacing (gap, padding) comes from spacing variables
  • Every frame uses Auto Layout
  • Interaction states (hover, focus, disabled, loading) exist as component variants
  • Loading, empty, error, and edge-case states are shown for every screen
  • Real copy is used in place of lorem ipsum
  • Breakpoint-specific frames are annotated
  • Interactive prototype is linked for complex flows

On this page