Nextjs figma conversion
Converts a running Next.js / React + Tailwind web app into a faithful, editable Figma design file — design tokens as Figma variables, shared UI as components, and every route as a pixel-matched screen frame. Use when the user wants to export, convert, recreate, mirror, or "preserve" a Next.js / React app's design in Figma, or turn code/screens into a Figma design file.From its SKILL.md
npx -y skills add Tar-ive/agent-skills --skill nextjs-figma-conversionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.6 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
Next.js → Figma Conversion
Turn a running web app into a native, editable Figma file. The strategy is capture, then reconstruct: there is no automatic code→Figma exporter, so we drive the rendered app to extract exact geometry, then rebuild it in Figma via the Plugin API. This produces real Figma variables, components, and frames — not flat screenshots.
Prerequisites
- The Figma MCP server is connected (see
mcp__plugin_figma_figma__*tools). If not, call itsauthenticatetool and have the user approve the OAuth URL. - Always load the
figma-useskill before everyuse_figmacall — it is a hard requirement and prevents common failures. - The app builds and runs locally (
npm/pnpm/yarn dev). - A real Chrome is installed (the scripts drive it via
playwright-corewithchannel: 'chrome', avoiding a ~150 MB browser download).
The pipeline (run in order)
Copy scripts/ into the project (e.g. scripts/figma-export/) and create a
figma-export.config.json from assets/figma-export.config.example.json. All
scripts read that config (path overridable as argv[2]).
- Explore & confirm scope. Read
package.json,app//pages/, the global CSS (design tokens /:rootCSS variables),components.json, and the shared components. List every route. For dynamic routes ([id]) find a real id from fixture/seed data. Decide scope with the user: full (tokens + components + all screens), key screens, or tokens-only. - Run the app.
pnpm installthen start the dev server in the background. Verify each route returns 200 (curl -o /dev/null -w "%{http_code}"). - Install the capture dep.
pnpm add -D playwright-core. - Screenshot every route —
node scripts/figma-export/screenshot.mjs. These are your fidelity reference (and what you compare Figma output against). - Extract DOM geometry —
node scripts/figma-export/extract-layout.mjs. Walks the rendered DOM and emits, per element, absolutex/y/w/h, background, border, radius, opacity, and text (content, color, font size/weight/family). Colors are resolved through a<canvas>so Tailwind v4oklch/color-mixvalues come back as sRGB, and alpha is preserved separately. - Flatten —
node scripts/figma-export/flatten.mjs. Converts each DOM tree into a preorder, absolutely-positioned node list (parents before children → correct paint/z-order when appended flat to one frame). - Generate renderer scripts —
node scripts/figma-export/gen-figma.mjs. Writes one self-containeduse_figmascript per route (renderer + inline data), laid out left-to-right on the canvas, each under the 50 KB code limit.
Build the Figma file
- Create the file with
mcp__plugin_figma_figma__create_new_file(editorTypedesign). If the user has multiple plans, ask which team. Make three pages:🎨 Tokens,🧩 Components,📐 Screens. - Tokens — create one variable collection from the CSS variables. Colors get
color-usage scopes (
FRAME_FILL,SHAPE_FILL,TEXT_FILL,STROKE_COLOR); radii areFLOATwith scopeCORNER_RADIUS. Bind each to a swatch so it doubles as a living reference. Seereferences/figma-build.md. - Components — build the repeated UI (nav/sidebar, badges, chips, buttons,
list rows, panels) as variant sets (
combineAsVariants) bound to the token variables. SVG logos/icons import cleanly viafigma.createNodeFromSvg— substitutecurrentColorwith a real hex in the string first. - Screens — for each generated script, Read it and pass its contents as the
codearg touse_figma. The renderer is idempotent (it removes any existing frame of the same name first), so re-running a single screen is safe. - Validate — screenshot one representative screen with
get_screenshot, compare to the reference PNG, fix the renderer if needed, regenerate, re-run. The demo/first screen is the canary: once it matches, the rest use the identical renderer.
Critical gotchas (these will bite you)
Read references/figma-gotchas.md for the full list. The highest-impact ones:
- Tailwind v4 colors are
oklch/color-mix.getComputedStylereturns them literally; naive RGB parsing yields garbage (e.g. aprimary/10tint becomes#010000). The extractor resolves every color via a 1×1 canvas → sRGB. - Preserve alpha as fill opacity. A semi-transparent bg flattened to an opaque
hex hides its own text. Capture alpha separately and set it as the Figma paint's
opacity(and capture elementopacitytoo). setBoundVariableForPaintdrops opacity. Setopacityon the returned paint, not the input:{...figma.variables.setBoundVariableForPaint(p,'color',v), opacity: o}.- Render box AND text for combined nodes. An element with both a background and direct text (buttons, badges, chips) must produce a frame and a text node, or you lose the background. Center the text within the box.
- Hug single-line text; fix width only for paragraphs. Figma's font metrics are
slightly wider than the browser's, so a fixed-width single-line label wraps. Use
WIDTH_AND_HEIGHTfor single lines (heuristic:h <= fontSize*1.7) andHEIGHT(fixed width) only for true multi-line text. - Clamp radius.
border-radius: 9999pxarrives as a huge number; clamp tomin(r, w/2, h/2). use_figmacodeis capped at 50 KB. Keep per-screen payloads small (compact JSON, short keys); split very large screens across calls if needed.- Switch pages with
await figma.setCurrentPageAsync(page)— the sync setter throws. Set it at most once per call.
Figma MCP rate limits (plan ahead)
Only read tools (get_screenshot, get_metadata, get_design_context,
get_variable_defs) count against limits. Write tools (use_figma,
create_new_file, whoami) are exempt. Caps by plan/seat:
| Seat | Starter | Professional | Organization | Enterprise |
|---|---|---|---|---|
| View / Collab | 6/mo | 6/mo | 6/mo | 6/mo |
| Dev / Full | 6/mo | 200/day · 10/min | 200/day · 15/min | 600/day · 20/min |
Implication: spend screenshots sparingly. On Starter you get ~6 reads/month — verify the canary screen, then trust the validated renderer for the rest. You can keep building/editing freely because writes don't count.
Files in this skill
scripts/—_config.mjs,screenshot.mjs,extract-layout.mjs,flatten.mjs,gen-figma.mjs.references/figma-build.md— variable/component/screen build details & snippets.references/figma-gotchas.md— every known pitfall with the fix.assets/figma-export.config.example.json— config template.
What ships with it: 8 files
19.0 KB alongside SKILL.md, 5 of them executable
assets/
references/
- figma-build.md3.1 KB
- figma-gotchas.md4.0 KB
scripts/
- _config.mjsruns910 B
- extract-layout.mjsruns3.7 KB
- flatten.mjsruns1.9 KB
- gen-figma.mjsruns4.1 KB
- screenshot.mjsruns859 B