Goal: stand up a structured Figma file (page-per-screen, variant-rich), seed it from the published editable figma-SVGs, then wire design-parity to compare candidates against Figma as the primary reference (design-led). Model agreed: seed-from-renders → then authoritative (designers refine in Figma; code is judged against it). Figma is primary; the committed HTML references can stay as a lower-precedence fallback.
Most of design-parity is already built for this — @design-parity/adapter-figma, the resolver's Code Connect path, and the figma-plugin importer all exist. This is wiring + authoring, not greenfield.
Why this is a local runbook (not the cloud agent)
The cloud session cannot inject assets into Figma:
- The Figma upload host (
mcp.figma.com) is blocked by the cloud session's egress policy (403 CONNECT) — so upload_assets POSTs fail there. Locally this works.
figma.createImageAsync(url) is not supported in the use_figma plugin sandbox.
fetch() is not defined in the use_figma sandbox (true locally too) — so createNodeFromSvg(svg) needs the SVG text embedded in the use_figma code, which means reading the SVG from a local checkout. A local session can do that; the cloud one can't reproduce 8–22 KB of vector data byte-exact by hand.
use_figma code is capped at 50 000 chars, so component SVGs >~48 KB (button-*, segmentedbutton, fab, template-appscaffold = 64 KB) can't be inlined — use a PNG via upload_assets for those (works locally). All screen SVGs are <22 KB and inline fine.
Already done this session (safe to build on)
Figma file: https://www.figma.com/design/gYzowY4cQ7rNr2gYoco1M6
Page 1 left untouched; 8 new pages created:
| Page |
id |
| Themes |
47:2 |
| Components |
47:3 |
| Device |
47:4 |
| Cached device |
47:5 |
| Contact chat |
47:6 |
| Channel chat |
47:7 |
| Commands |
47:8 |
| Device settings |
47:9 |
Seed source — editable figma-SVGs
Published on the design-artifacts/meshcore-mobile branch under figma/<slug>.svg (140 files, the "ideal render as native vectors"; also wireframes/<slug>.svg for the layout wireframes). Screen → slug mapping:
| Page (id) |
figma-SVG slugs |
Device (47:4) |
device-loading, device-lowbattery, device-manycontacts, device-nocontacts, device-statusconnecting, device-statusfailed |
Cached device (47:5) |
device-cached |
Contact chat (47:6) |
chat-contact |
Channel chat (47:7) |
chat-channel |
Commands (47:8) |
chat-commands |
Device settings (47:9) |
settings-ready |
Themes (47:2) |
theme-meshcore-light, theme-meshcore-dark, theme-material3-light, theme-material3-dark + variables from design/meshcore.tokens.json |
Components (47:3) |
button-*, chip-*, card-*, switch-on, checkbox-checked, radiobutton-selected, progress-*, slider, textfield-*, fab, segmentedbutton, badge … (several >48 KB → PNG upload, not SVG inline) |
Local runbook
- Checkout the SVG source:
git fetch origin design-artifacts/meshcore-mobile
git worktree add /tmp/mesh-figma-svgs origin/design-artifacts/meshcore-mobile
- Seed each screen page — one
use_figma call per variant (read the SVG file, createNodeFromSvg, place, caption). Template (Device / loading):
// read /tmp/mesh-figma-svgs/figma/device-loading.svg into `svgText`, then:
const page = await figma.getNodeByIdAsync("47:4"); // Device
await figma.setCurrentPageAsync(page);
const node = figma.createNodeFromSvg(svgText); // svgText = the file contents
node.name = "Device — loading";
// lay out in a captioned grid (auto-layout row); x/y or wrap into a section
page.appendChild(node);
return { id: node.id, w: Math.round(node.width), h: Math.round(node.height) };
Keep ≤ a few nodes per call; return node ids (you'll need them for the design-map). Alternatively run design-parity's figma-plugin in Figma — it imports the published catalog with a11y greenlines / redlines / token variable collection / design-map scaffold — but note it lays out component-grouped, not page-per-screen, so the custom createNodeFromSvg loop above is what matches this file's structure.
- Themes page: create a Figma variable collection with
light/dark modes from design/meshcore.tokens.json (M3 color roles + shape radii + spacing). This is what design-parity's token-compliance diff consumes.
Wire design-parity to compare against Figma
- Map each code handle → Figma node. Options, highest precedence first:
- Code Connect (
figma connect CLI → static map "…Kt#DeviceBodyPreview" → "figma:gYzowY4cQ7rNr2gYoco1M6/<nodeId>") — the resolver's top source, no live call at resolve time.
- or the
figma-plugin's design-map.json correspondence carrying figma: refs (same resolver, lower precedence) — use if Code Connect isn't available on the Figma plan.
- Point references at
@design-parity/adapter-figma (resolves figma:<fileKey>/<nodeId> → reference image + tokens for the diff).
- CI: add a
FIGMA_TOKEN repo secret; design-parity.yml needs it for adapter-figma node export + Code Connect materialization.
- Flip direction:
.design-parity.json "direction": "code-led" → "design-led" once thresholds calibrate (keep code-led advisory during migration so nothing goes red mid-cutover).
Open decisions / notes
- Parity subjects gap: the current Device parity subjects —
DeviceBodyPreview (populated, light) and DeviceBodyDarkPreview — are not in the catalog figma-SVG set (the catalog carries the state variants + device-cached, not the plain populated/dark). For the compare wiring those two specific nodes need a Figma reference: either render them to SVG and add them, author them in Figma, or map parity to the nearest catalog variant. Decide per screen.
:app vs :meshcore-components chrome: the state variants render on :app (Robolectric, with an OS status bar); the parity subjects render on :meshcore-components (CMP desktop, no status bar). Keep that in mind when arranging a page so the frames read consistently.
- Two SVG flavors available:
figma/ (ideal styled render) and wireframes/ (layout spec) — could show both per variant later.
References
docs/design-parity.md (this repo) — reference model, render path, design-map.json, .design-parity.json.
scripts/figma-import-prep.mjs + docs/design-artifacts/FIGMA_IMPORT.md (design-parity repo) — the catalog→Figma import playbook.
- design-parity packages:
adapters/adapter-figma, resolver (Code Connect precedence), figma-plugin (importer + design-map export).
Generated by Claude Code
Goal: stand up a structured Figma file (page-per-screen, variant-rich), seed it from the published editable figma-SVGs, then wire design-parity to compare candidates against Figma as the primary reference (
design-led). Model agreed: seed-from-renders → then authoritative (designers refine in Figma; code is judged against it). Figma is primary; the committed HTML references can stay as a lower-precedence fallback.Most of design-parity is already built for this —
@design-parity/adapter-figma, the resolver's Code Connect path, and thefigma-pluginimporter all exist. This is wiring + authoring, not greenfield.Why this is a local runbook (not the cloud agent)
The cloud session cannot inject assets into Figma:
mcp.figma.com) is blocked by the cloud session's egress policy (403 CONNECT) — soupload_assetsPOSTs fail there. Locally this works.figma.createImageAsync(url)is not supported in theuse_figmaplugin sandbox.fetch()is not defined in theuse_figmasandbox (true locally too) — socreateNodeFromSvg(svg)needs the SVG text embedded in theuse_figmacode, which means reading the SVG from a local checkout. A local session can do that; the cloud one can't reproduce 8–22 KB of vector data byte-exact by hand.use_figmacodeis capped at 50 000 chars, so component SVGs >~48 KB (button-*,segmentedbutton,fab,template-appscaffold= 64 KB) can't be inlined — use a PNG viaupload_assetsfor those (works locally). All screen SVGs are <22 KB and inline fine.Already done this session (safe to build on)
Figma file: https://www.figma.com/design/gYzowY4cQ7rNr2gYoco1M6
Page 1 left untouched; 8 new pages created:
47:247:347:447:547:647:747:847:9Seed source — editable figma-SVGs
Published on the
design-artifacts/meshcore-mobilebranch underfigma/<slug>.svg(140 files, the "ideal render as native vectors"; alsowireframes/<slug>.svgfor the layout wireframes). Screen → slug mapping:47:4)device-loading,device-lowbattery,device-manycontacts,device-nocontacts,device-statusconnecting,device-statusfailed47:5)device-cached47:6)chat-contact47:7)chat-channel47:8)chat-commands47:9)settings-ready47:2)theme-meshcore-light,theme-meshcore-dark,theme-material3-light,theme-material3-dark+ variables fromdesign/meshcore.tokens.json47:3)button-*,chip-*,card-*,switch-on,checkbox-checked,radiobutton-selected,progress-*,slider,textfield-*,fab,segmentedbutton,badge… (several >48 KB → PNG upload, not SVG inline)Local runbook
use_figmacall per variant (read the SVG file,createNodeFromSvg, place, caption). Template (Device / loading):figma-pluginin Figma — it imports the published catalog with a11y greenlines / redlines / token variable collection / design-map scaffold — but note it lays out component-grouped, not page-per-screen, so the customcreateNodeFromSvgloop above is what matches this file's structure.light/darkmodes fromdesign/meshcore.tokens.json(M3 color roles + shape radii + spacing). This is what design-parity's token-compliance diff consumes.Wire design-parity to compare against Figma
figma connectCLI → static map"…Kt#DeviceBodyPreview" → "figma:gYzowY4cQ7rNr2gYoco1M6/<nodeId>") — the resolver's top source, no live call at resolve time.figma-plugin'sdesign-map.jsoncorrespondence carryingfigma:refs (same resolver, lower precedence) — use if Code Connect isn't available on the Figma plan.@design-parity/adapter-figma(resolvesfigma:<fileKey>/<nodeId>→ reference image + tokens for the diff).FIGMA_TOKENrepo secret;design-parity.ymlneeds it foradapter-figmanode export + Code Connect materialization..design-parity.json"direction": "code-led"→"design-led"once thresholds calibrate (keepcode-ledadvisory during migration so nothing goes red mid-cutover).Open decisions / notes
DeviceBodyPreview(populated, light) andDeviceBodyDarkPreview— are not in the catalog figma-SVG set (the catalog carries the state variants +device-cached, not the plain populated/dark). For the compare wiring those two specific nodes need a Figma reference: either render them to SVG and add them, author them in Figma, or map parity to the nearest catalog variant. Decide per screen.:appvs:meshcore-componentschrome: the state variants render on:app(Robolectric, with an OS status bar); the parity subjects render on:meshcore-components(CMP desktop, no status bar). Keep that in mind when arranging a page so the frames read consistently.figma/(ideal styled render) andwireframes/(layout spec) — could show both per variant later.References
docs/design-parity.md(this repo) — reference model, render path,design-map.json,.design-parity.json.scripts/figma-import-prep.mjs+docs/design-artifacts/FIGMA_IMPORT.md(design-parity repo) — the catalog→Figma import playbook.adapters/adapter-figma,resolver(Code Connect precedence),figma-plugin(importer + design-map export).Generated by Claude Code