feat: wireframe designer, Satori rendering, and Copy to Figma#24
Merged
trmquang93 merged 7 commits intomainfrom Apr 4, 2026
Merged
feat: wireframe designer, Satori rendering, and Copy to Figma#24trmquang93 merged 7 commits intomainfrom
trmquang93 merged 7 commits intomainfrom
Conversation
Replace Puppeteer with Satori (Vercel) in the MCP server for HTML-to-PNG rendering. Satori produces clean native SVG alongside the PNG, eliminating the Chrome binary requirement and reducing render time from ~2s to ~50ms. Add a built-in wireframe designer that lets users sketch screens directly in Drawd using a drag-and-drop component palette (rect, button, input, nav-bar, tab-bar, and more). Wireframes render to PNG via the browser canvas and store their component schema for re-editing. Both MCP screens (via Satori) and wireframe screens export to Figma as editable SVG vector layers via right-click → Copy for Figma or Download SVG. Details: - mcp-server: SatoriRenderer replaces HtmlRenderer; returns svgString + pngBuffer; bundles Inter font; esbuild marks @resvg/resvg-js external - File version bumped 12 → 13; screens gain svgContent, sourceHtml, wireframe - useWireframeEditor hook: full undo/redo, grid snapping, component CRUD - WireframeEditor: SVG canvas with drag/resize, keyboard shortcuts, auto- hotspot generation from interactive components - copyToFigma utility: clipboard SVG copy + SVG file download - Backward compat: importFlow.js backfills new fields for v1–12 files - Docs: updated user guide with wireframe designer and Figma export sections
Satori requires every element with multiple children to have an explicit display property — default block/inline layout does not exist. Add injectMissingDisplay() to auto-inject display:flex;flex-direction:column on div/section/header/footer/main/nav elements whose style lacks a display declaration. Also improve create_screen and update_screen_image tool descriptions to clearly document Satori's rendering constraints for AI agent callers.
- Add copyScreensForFigma() combining multiple screen SVGs into one document using <g translate> per screen, preserving canvas-relative positions scaled to SVG coordinate space - Add prefixSvgIds() to prevent ID collisions (gradients, patterns) when merging multiple SVGs into a single document - Wire prepareSvgForFigma() into copyScreenForFigma() and downloadScreenSvg() so single-screen exports also get gradient fixes - Context menu shows "Copy N Screens for Figma" when right-clicking within a multi-screen selection; falls back to "Copy for Figma" for single screens - Toast message adapts: "3 screens copied — paste in Figma" vs "SVG copied — paste in Figma"
- Import generateId from utils instead of redefining locally - Fix drag undo: snapshot pre-drag (captureDragSnapshot) instead of post-drag (commitMove), making drag/resize operations undoable - Remove unused moveComponent from useWireframeEditor API - Remove redundant selectedComp re-derivation; use hook's selectedComponent - Skip getBoundingClientRect on mousemove when no drag/resize is active - Fix button fill default in ComponentShape to match wireframeToSvg (#333333) - Collapse dead ternary in renderText (both branches were identical) - Use WIREFRAME_VIEWPORT_WIDTH/HEIGHT constants and deduplicate onAddWireframe - Reuse downloadZip from zipBuilder in downloadScreenSvg
- Add _autoSave() to FlowState and call it after every mutation (addScreen, updateScreen, deleteScreen, addHotspot, addConnection, etc.) so changes are written to disk immediately without an explicit save_flow call - Add filePath as a required parameter to all non-file tools via withFilePath() in server.js; the request handler auto-loads the file on the first call so Claude never needs a separate open_flow call to establish session context - Update screen-tools HTML description with Figma-compatibility rules - Add api script to mcp-server/package.json
- Add copyScreensForFigmaEditable() using fig-kiwi to write Figma's native binary clipboard format; pasted screens arrive as editable frames with fills, text nodes, and corner radii rather than flat SVG vectors - Add htmlToFigmaNodes, figmaClipboard, figKiwiWriter, diffPayload utilities and figmaSchema.json to support the conversion pipeline - Add "Copy as Editable" context menu entry in CanvasArea for wireframe screens - Flash canvas items that were mutated by an MCP tool call (mcpFlashIds + CSS keyframe animations in ScreenNode, StickyNote, ConnectionLines) - Push undo snapshot before applying MCP payloads so MCP edits are undoable - Add MCP HTTP API server (mcp-server/src/api-server.js) and top-level api.js - Add figma-plugin/ reference files for clipboard format reverse-engineering - Add test coverage for figKiwiWriter, figmaClipboard, copyToFigma, wireframeToSvg, and useWireframeEditor
Single-line text nodes (height < 1.5× lineHeight) now use WIDTH_AND_HEIGHT auto-resize so Figma never re-flows them regardless of font metric differences. Multi-line text gets a +1px width buffer in layoutSize.x to absorb per-character drift. Text widths are ceiled to avoid sub-pixel rounding. Text inside non-auto-layout visual containers (badges, pills) is now positioned at (paddingLeft, paddingTop) instead of (0, 0), and its width is reduced by horizontal padding — fixing labels like "VIP" and "Nóng" overlapping their frame edges and wrapping.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
screen.svgContent.Wtoolbar button opens a full-screen SVG canvas editor. Drag components (rect, button, input, nav-bar, tab-bar, etc.) from a palette, edit properties in the right panel, and click Done to render a PNG. Interactive components auto-generate hotspots.Changes
mcp-server:SatoriRendererreplacesHtmlRenderer; bundles Inter font;@resvg/resvg-jsmarked external in esbuild config; font assets copied todist/assets/at build timesrc/constants.js:FILE_VERSION12 → 13; addsWIREFRAME_GRID_SIZE,WIREFRAME_VIEWPORT_WIDTH/HEIGHTsrc/hooks/useWireframeEditor.js: component CRUD, undo/redo (ref-based), grid snapsrc/components/wireframe/:WireframeEditor,ComponentPalette,PropertyPanelsrc/utils/wireframeToSvg.js,wireframeRenderer.js,wireframeDefaults.js: SVG generation and PNG renderingsrc/utils/copyToFigma.js: clipboard copy + SVG file downloadsrc/utils/importFlow.js: backfillssvgContent,sourceHtml,wireframefor v1–12 filessrc/pages/docs/userGuide.md: new Wireframe Designer and Copy to Figma sectionsTest plan
npm test— 358 tests passnpm run build— clean production buildcd mcp-server && node --input-type=moduletest withSatoriRendererrenders PNG + SVGnpm run buildinmcp-server/producesdist/index.js+dist/assets/fonts.drawdfile — loads without errors, new fields default tonullsvgContent→ Copy for Figma → paste in Figma shows editable vectors