← Back to blog

Code Connect

Figma Code Connect: A Practical Guide

DesignGuard AI9 min read

I've spent a lot of time lately in the guts of Figma Code Connect — enough that I want to write down the version of this guide I wish existed when we started. Figma's own docs are accurate but scattered across a dozen pages. This is the practical, start-to-finish version: what Code Connect actually does, how to set it up by hand, and the specific things that trip people up once they've got more than a handful of components.

What Code Connect actually does

Here's the problem it solves. A developer opens a Figma file in Dev Mode, wanting to build a button they see on the canvas. Figma can show them CSS values, spacing, and export assets — but it has no idea that your team already has a <Button> component sitting in your repo, with its own props and its own conventions. So the developer either goes hunting for it, or just writes a new one. Multiply that by a growing team and you get five slightly different buttons.

Code Connect closes that gap. You write a small file that says "this Figma component maps to this real code component, and here's how its Figma properties map to real props." Once it's published, Dev Mode shows the actual code snippet — real component, real props, real import path — instead of raw CSS.

It's a genuinely good idea. The catch is that writing these files by hand, one per component, is tedious in a very specific way: not hard, just fiddly, and the kind of task that quietly stops happening once the backlog gets past ten components.

Two ways to set it up

Figma gives you two paths in:

Code Connect UI — entirely inside Figma, no CLI, no local repo access required. You connect a GitHub repository or manually point at file paths and component names. It's the lower-friction option, especially if you're not the one with edit access to the codebase.

Code Connect CLI — you write actual template files in your repo (.figma.tsx, .figma.ts, etc.), and publish them with a CLI command. More setup, but more control — and it's what I'll walk through here, since it's what most engineering-led teams end up using once they're doing this seriously.

Both feed the same underlying system, so it's not really an either/or — some teams use the UI for quick wins on simple components and the CLI for anything with real prop complexity.

Setting it up, step by step

Install the CLI as a dev dependency:

npm install --save-dev @figma/code-connect

Run the init command and it'll ask a few questions — mainly your Figma file URL and where your components live:

npx figma connect init

That gives you a figma.config.json in your repo root. This is where Code Connect learns things like your import path style — worth setting up correctly once, since it's what determines whether the generated import line in Dev Mode is import { Button } from "@/components/button" or some awkward relative path guess.

Writing your first file

Here's roughly what a real one looks like, for a Button component with a size and disabled variant:

import { Button } from "../components/button";
import figma from "@figma/code-connect";

figma.connect(Button, "https://www.figma.com/design/xxxx/?node-id=12-4980", {
  props: {
    label: figma.string("Label"),
    size: figma.enum("Size", {
      "Small": "sm",
      "Large": "lg",
    }),
    disabled: figma.boolean("Disabled"),
  },
  example: (props) => (
    <Button label={props.label} size={props.size} disabled={props.disabled} />
  ),
});

A few things worth understanding about this, not just copying it:

  • The second argument to figma.connect is the actual node URL of the component (or component set) in Figma — you get this by right-clicking the component and copying its link.
  • figma.enum, figma.boolean, and figma.string map a Figma property to a real prop. The keys inside figma.enum have to match your Figma variant options exactly, including capitalization — this is the single most common source of "why isn't this working" I've seen.
  • example is what actually renders in Dev Mode's code panel. It's a real JSX snippet, not a description of one — treat it like code a developer would genuinely copy and paste.

Once you've got a handful of these written, publish them:

npx figma connect publish --token=YOUR_PERSONAL_ACCESS_TOKEN

(You can set FIGMA_ACCESS_TOKEN as an environment variable instead of passing --token every time, which is worth doing the moment you're running this more than once.) The CLI prints the components it published along with links to each node — click through and confirm what you expected to see is actually showing up in Dev Mode. Don't skip this step; it's the fastest way to catch a variant name mismatch before it sits unnoticed for a month.

The parts that actually trip people up

This is the section I most wanted to write, because it's the stuff you only learn by doing this across a real, messy, actually-used component library — not a clean example.

Variant instance naming. If a component is discovered through an instance inside a frame rather than through the main component library, its name can come back as a raw variant string (like Size=Large, State=Default) instead of the real component name. If your mapping logic — or a person doing this by hand — grabs the name from the wrong place, you'll write a Code Connect file against a name that doesn't mean anything to anyone. Always resolve back to the actual component set name.

Enum values are a guess, not a certainty, unless you tell them otherwise. figma.enum("Size", { "Small": "sm", "Large": "lg" }) — that right-hand side, the real code value, isn't something Code Connect can know on its own. If your code has a TypeScript string-literal union type for that prop (size?: "sm" | "md" | "lg"), that's a genuine hint you can match against. Without it, you're guessing, and a wrong guess sitting in a "confirmed" file is worse than an obvious TODO — it looks authoritative and isn't.

Path aliases matter more than they seem to. A generated example block with a relative import like ../../../components/button is technically correct and practically useless — nobody wants to copy that. If your tsconfig.json or jsconfig.json already defines a @/*-style alias, use it. This is a small detail that's the difference between a Code Connect snippet developers actually paste versus one they silently ignore and rewrite themselves.

Don't overwrite work someone already did by hand. If a figma.connect(...) file already exists for a component — because someone wrote and customized it manually — a bulk regeneration process needs to detect that and leave it alone. This sounds obvious until you're the one who wiped out a hand-tuned file with a bulk export.

Staleness is a real, ongoing problem, not a one-time setup cost. Components change. Props get renamed. Figma variants get added. A Code Connect file that was accurate the day you wrote it can quietly go stale the next time someone touches the component — and there's nothing in the file itself that tells you that happened. Worth having some process, even a manual one, for periodically re-checking your published files against the current state of both sides.

When it's worth automating this

Hand-writing Code Connect files is completely reasonable for a design system with a dozen or so core components — it's a few hours of work, and honestly a good way to develop a real feel for how variant mapping works before you automate anything.

Where it stops being reasonable is scale: fifty, a hundred components, prop mappings that shift as the library evolves, and the fact that "write the Code Connect files" tends to be the kind of task that's important but never quite urgent enough to get done. That's the exact gap we built DesignGuard AI to close — it reads your actual Figma variant properties and your actual code props, generates the scaffold file with everything below high confidence explicitly marked with a TODO instead of a silent guess, and flags files as stale automatically once either side changes. It's not magic — anything uncertain still gets a TODO, same as if you'd written it by hand and weren't sure. It's just the tedious 80% done for you, so the review is the only part left that actually needs a person.

Either way — by hand or automated — the thing that matters is starting. A Code Connect setup that covers your ten most-used components honestly beats an ambitious plan to cover all two hundred that never quite gets off the ground.

See it on your own design system

Run a DesignGuard AI audit against a real Figma frame or repo.

Open dashboard

More posts

Keep reading.

View all posts

Product updates

DesignGuard Now Re-Scans Your Figma Files the Moment You Publish

Read post

Design systems

What Is a Design System Audit?

Read post