mcpField
P
penpot-migrate

penpot-migrate

github.com/penpotDesign & UI108115 installsUpdated 3w ago
Repository

About penpot-migrate

penpot-migrate is a skill for moving Figma designs into Penpot, building an intermediate representation before translating tokens, components, and screens in stages. It can read through Figma MCP or use pasted exports, and checks structural and visual fidelity along the way.

Key features

  1. 01Builds an intermediate representation before Penpot writes
  2. 02Migrates variables, tokens, components, and screens
  3. 03Maps Auto Layout to flex or grid
  4. 04Validates migration in stages
  5. 05Reports fidelity gaps

Use cases

  1. 01Move a Figma design system into Penpot
  2. 02Create a Penpot file from pasted Figma exports
  3. 03Review migrated layouts and visuals screen by screen

MCP support

The skill reads design data through Figma MCP and creates and validates target content through Penpot MCP. It can also work from pasted exports when Figma MCP is unavailable.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/penpot/penpot-ai-kit --skill penpot-migrate

After installing, type/penpot-migratein Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
01-figma-analysis.md
02-ir-building.md
03-token-migration.md
04-component-migration.md
05-layout-translation.md
06-screen-migration.md
07-validation.md
08-error-recovery.md
scripts/
analyzeFigmaStructure.js
buildIR.js
migrateComponent.js
migrateScreen.js
migrateTokens.js
validateFidelity.js

Details

From the project README

penpot-migrate — Figma → Penpot, fidelity-first

1. Title + How it works

penpot-migrate bridges two MCP servers: it reads a Figma design via the Figma MCP and writes it into Penpot via the Penpot MCP — every mutation goes through execute_code; validate visually with export_shape; read structure with penpotUtils.shapeStructure (full tool surface: shared/penpot-mcp-tool-reference.md). It never writes Penpot directly from Figma data — it first builds a normalized intermediate representation (IR), then translates the IR into Penpot constructs (boards, flex, tokens, components). If the Figma MCP isn't available, it accepts manually-pasted Figma export/JSON and works from that.

2. The One Rule That Matters Most

IR before any Penpot write, and migrate in layers. Tokens first, then components, then screens — each validated. Never one-shot a whole file. The IR is the contract that decouples Figma's model from Penpot's API.

3. Penpot MCP Tool Reference

Full surface: shared/penpot-mcp-tool-reference.md. Penpot-write side: createBoard/addFlexLayout/ addGridLayout, penpot.library.local.tokens.addToken, createComponent/createVariantFromComponents, export_shape for fidelity checks. Figma-read side: the Figma MCP's design-context tools (names vary; treat them as producing raw data the IR normalizes).

4. Plugin API Essentials

Gotcha numbers refer to shared/plugin-api-gotchas.md.

  • Penpot uses Boards (not Frames); Auto Layout maps to Board flex (dir, gaps, padding, sizing fill/auto/fix) or grid.
  • Figma Variables → Penpot tokens via addToken({type,name,value}) with the real type strings (shared/tokens-schema.json). Map Figma modes → Penpot themes.
  • #9 Figma component sets/variants → Penpot variant containers: prefer penpotUtils.createVariantContainer([{ shape: mainInstance, properties }]) (≥ 2.17); penpot.createVariantFromComponents(mainInstances) is the low-level fallback; Board.combineAsVariants(ids) is listed on 2.17 but unverified — do not use. Beware #12 — variant mutation corrupts the file; prefer create-then-group, never edit a variant container in place.
  • #2 token application is async — apply in one call, verify resolvedValue/shape.tokens in a LATER call; #4 flex overrides child x/y; #6 detach before mutating instance internals.
  • Verify unfamiliar signatures with penpot_api_info first.

5. Token-Aware Brief Contract

  • Context — source Figma file/scope, target Penpot file, fidelity expectations.
  • Objective — single: "migrate from Figma to Penpot at ".
  • Inputs — Figma access (MCP or pasted export), naming/token mapping rules.
  • Constraints — preserve hierarchy/layout/variants; map Variables to tokens; on-grid spacing.
  • Acceptance Criteria — IR built; tokens migrated & resolving; components/variants reconstructed; screens visually match (export compare); fidelity report.

Act as a migration engineer who prizes structural fidelity.

6. Mandatory Workflow

Visual self-review (mandatory): before every ✋ checkpoint that shows visual work, run the export → look → fix loop from shared/visual-self-review.md — export the unit you just built, inspect the image yourself against the checklist, fix visible defects (max 2 iterations), and present that same export with any remaining defects named.

Phase 0 — Figma analysis. Read the source (Figma MCP or pasted data); inventory tokens/components/screens (scripts/analyzeFigmaStructure.js, references/01-figma-analysis.md). ✋ Checkpoint: scope & mapping rules.

Phase 1 — Build IR. Normalize into the IR (scripts/buildIR.js, references/02-ir-building.md). The IR is plain data; no Penpot writes yet. ✋ Checkpoint: review IR coverage.

Phase 2 — Tokens. Translate Variables → tokens (scripts/migrateTokens.js, references/03-token-migration.md); reconcile with penpot-foundations. ✋ Checkpoint.

Phase 3 — Components. Reconstruct components & variants (scripts/migrateComponent.js, references/04-component-migration.md). ✋ Checkpoint.

Phase 4 — Layout & screens. Auto Layout → flex/grid (references/05-layout-translation.md); build screens (scripts/migrateScreen.js, references/06-screen-migration.md). ✋ Checkpoint per screen (export_shape).

Phase 5 — Validate fidelity. scripts/validateFidelity.js (references/07-validation.md) — structure, tokens, visual compare. Report. (references/08-error-recovery.md for issues.)

7. Critical Rules

  1. Build the IR before any Penpot write.
  2. Migrate tokens → components → screens, in that order, validating each.
  3. Auto Layout → flex/grid; never absolute-position what was auto-laid-out.
  4. Variables → tokens with real type strings; modes → themes.
  5. Degrade gracefully if the Figma MCP is absent (accept pasted data).
  6. Report fidelity gaps honestly; don't claim 1:1 when it isn't.

8. Domain Architecture

IR (plain JSON) decouples the two tools:

{ tokens:[{type,name,value,mode?}],
  components:[{name, variantProps?, layout, children:[...]}],
  screens:[{name, size, layout, children:[...]}] }

Each IR node carries enough to build the Penpot equivalent (layout = flex/grid spec; children reference components or primitives). Translation reads IR, writes Penpot.

9. Modes & Policies

Default review. Component/variant restructuring and detach never auto (shared/modes-and-policies.md).

10. State Management

Ledger under RUN_ID: phase, ir (or a pointer), migrated:{tokens,components,screens}, gaps:[...]. The IR is the resumable artifact — re-read it after truncation.

11. User Checkpoints

After phaseArtifactsAsk
0inventory + mapping rulesApprove scope/mapping?
1IR coverageApprove IR?
2migrated tokens (tokenOverview)Approve tokens?
3components/variantsApprove components?
4screen export_shapeApprove screen?

12. Naming Conventions

shared/naming-conventions.md: map Figma names to Penpot conventions (PascalCase components, Property=Value variants, semantic layers, dot-notation tokens).

13. Anti-Rationalization Table

ExcuseWhy it's wrongCountermeasure (halt)
"Skip the IR, write Penpot straight from Figma."Couples the two models; brittle, lossy.Build the IR first; translate from it.
"Absolute-position everything to match pixels."Loses Auto Layout responsiveness.Map Auto Layout → flex/grid; absolute only where Figma used absolute.
"Recreate Variables as hardcoded values."Drops the token system.Migrate Variables → tokens; modes → themes.
"Migrate the whole file in one pass."One-shot loses fidelity and is unauditable.Layered: tokens → components → screens, validate each.
"Figma MCP isn't connected, so I'll guess the design."Guessing fabricates the design.Ask for a pasted export/JSON; work from real data.
"Claim it's a perfect 1:1."Some Figma features don't map cleanly.Report fidelity gaps honestly.

14. Helper Code Snippets

// Translate an IR layout node to a Penpot flex Board
function buildFromIR(node, parent){
  const b = penpot.createBoard(); b.name = node.name;
  if (node.layout && node.layout.type === "flex"){
    const f = b.addFlexLayout();
    f.dir = node.layout.dir || "column";
    f.rowGap = node.layout.rowGap || 0; f.columnGap = node.layout.columnGap || 0;
  }
  (parent || penpot.currentPage.root).appendChild(b);
  return b;
}
return { ok: true };

15. Reference Resources

  • penpot_api_info('Board'), penpot_api_info('VariantContainer'), penpot_api_info('TokenSet').
  • Figma MCP design-context tools (names vary by version) — discover via the Figma MCP's own overview.

16. Supporting Files

references/: 01-figma-analysis.md, 02-ir-building.md, 03-token-migration.md, 04-component-migration.md, 05-layout-translation.md, 06-screen-migration.md, 07-validation.md, 08-error-recovery.md. scripts/: analyzeFigmaStructure.js, buildIR.js, migrateTokens.js, migrateComponent.js, migrateScreen.js, validateFidelity.js.

Doctrine paths. shared/… and policies/… resolve inside this bundle in native installs (vendored by the installer); in a Claude Code plugin install they live at the plugin root — ${CLAUDE_PLUGIN_ROOT}/shared/…, two directories up from this file.

Comments

Markdown supported