Generate production-ready React + styled-components code directly from any Figma frame. The plugin runs in Dev Mode, analyses your component structure, and produces two parallel panels of code you can copy straight into your codebase.
| Pattern detected | Component output | Styles output |
|---|---|---|
| Carousel / Slider | useState with prev/next/dots + autoPlay |
Container, Track, Buttons, Dots |
| List | Maps items[] prop with empty state |
ul + item wrappers |
| Grid | CSS Grid with configurable columns | Auto-detected column count |
| Card | Props for text, image, CTA, icon | article with all child styles |
| Navbar | logo, links[], optional CTA prop |
nav, links list, button |
| Hero | heading, subheading, two CTAs, backgroundImage |
Full-bleed section with z-layering |
| Tabs | useState + TabItem[] with accessible roles |
Tab list, buttons with $active prop |
| Form | useState per field + onSubmit handler |
Input, Textarea, Label, Submit |
| Generic | Tree-walking JSX + auto text/image props | All child nodes as styled components |
- Node.js 18+
- Figma desktop app (Dev Mode requires a paid plan or free Dev Mode access)
npm install
npm run build # production build → dist/
npm run watch # development watch mode- Open Figma desktop → Plugins → Development → Import plugin from manifest...
- Select
manifest.jsonfrom this folder - Switch to Dev Mode in the toolbar (the
</>icon) - Select any frame → open the Inspect panel → choose React + Styled Components from the language dropdown
figma-codegen-plugin/
├── manifest.json # Plugin manifest (editorType: dev, codegen capabilities)
├── webpack.config.js # Two bundles: sandbox code + UI iframe
├── tsconfig.json
├── src/
│ ├── code.ts # Main thread: codegen event → analyse → generate → postMessage
│ ├── analyser.ts # Detects pattern from node tree (carousel, list, grid…)
│ ├── styleExtractor.ts # Reads Figma node properties → CSS values
│ ├── generator.ts # Pattern-specific React + styled-components generators
│ ├── ui.html # Plugin iframe HTML (split panel UI)
│ └── ui.ts # Iframe script: receives code, renders it, handles copy
└── dist/ # Built output (committed or gitignored — your choice)
├── code.js
├── ui.html
└── ui.js
User selects frame in Figma Dev Mode
│
▼
figma.codegen.on('generate', { node }) ← fires on every selection change
│
├─→ analyser.ts Walk node tree, detect pattern + repeating children
│
├─→ styleExtractor.ts Read fills, strokes, layout, typography → CSS values
│
├─→ generator.ts Pattern dispatcher → build JSX + styled-components strings
│
├─→ CodegenResult[] Returned to Figma's native Inspect panel (2 sections)
│ Section 1: Component code (TYPESCRIPT)
│ Section 2: Styled-components (TYPESCRIPT)
│
└─→ figma.ui.postMessage → ui.ts renders split-panel view with syntax highlight + copy
Figma's native Inspect panel — two collapsible code sections appear automatically. Each has Figma's built-in copy button.
Plugin panel (custom UI) — a split-panel view with:
- Syntax-highlighted code
- Tab switching: Split / Component only / Styles only
- Copy buttons per panel with confirmation feedback
- Status bar showing detected pattern + component name
The analyser scores each node based on:
- Layer name keywords —
carousel,slider,hero,nav,header,form,grid,tabetc. - Layout mode —
HORIZONTALlayout + 2+ repeating children → carousel;VERTICAL→ list - Repeating children — groups nodes by type and finds the largest group of identical siblings
- Child content — presence of text nodes, image rectangles, button-named frames
Detection priority (most specific wins):
carousel > tabs > navbar > hero > form > grid > list > card > generic
Accessible via the gear icon in Figma's Inspect panel:
| Preference | Options | Effect |
|---|---|---|
| Tab Size | 2 / 4 | Indentation in generated code |
| Units | px / rem | All dimension values (16px vs 1rem) |
- Files:
ComponentName.tsx+ComponentName.styles.ts - Exports: Named styled-components exports, default component export
- Props: Derived from layer names — text layers become
stringprops, image rectangles becomeimageSrc/imageAlt - Repeating children: Become typed
ItemData[]interface passed asitemsprop - Transient props: Boolean/variant styled-component props use
$prefix (e.g.$active) per styled-components v5+ convention
| Figma practice | Why it helps |
|---|---|
| Name your layers meaningfully | Layer names become component names, prop names, and styled-component names |
| Use Auto Layout | Enables correct flexDirection, gap, padding extraction |
| Group repeating items | The analyser needs 2+ identically-typed siblings to detect lists/grids/carousels |
| Name image layers with "image", "photo", "thumbnail" | Generates as="img" with src/alt props instead of a blank div |
| Name button groups with "button", "btn", "cta" | Generates onClick handler props |
| Use solid fills (not gradients) for backgrounds | Only solid fills are extracted to backgroundColor |
- Gradient fills are not converted (complex CSS gradients from Figma data are lossy)
- Component instances are treated as regular frames — Figma component variables are not yet mapped to props
- Images inside fills (Figma image fills on rectangles) are detected by layer name, not fill type
- Auto Layout gaps require Figma's
itemSpacingproperty — absolute-positioned designs lose flexbox semantics - The 3-second codegen timeout — extremely deep or complex frames may hit Figma's limit; the plugin handles this gracefully by returning what it has
# Watch mode with source maps
npm run watch
# Type check only
npx tsc --noEmit
# Production build (minified, no source maps)
npm run buildTo add a new pattern:
- Add the pattern name to
ComponentPatterninanalyser.ts - Add detection logic in
analyseNode() - Add a generator function in
generator.ts - Register it in the
GENERATORSmap at the bottom ofgenerator.ts