Skip to content

Commit 11fecef

Browse files
authored
feat: wireframe designer, Satori rendering, and Copy to Figma (#24)
* feat: add wireframe designer, Satori rendering, and Copy to Figma export 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 * fix(mcp): inject missing display:flex for Satori compatibility 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. * feat: add multi-screen Copy for Figma support - 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" * fix: code quality cleanup for wireframe/Satori PR - 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 * fix(mcp): auto-save mutations and require filePath on all tools - 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 * feat: add editable Figma clipboard export and MCP visual feedback - 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 * fix: prevent text wrapping and misalignment in editable Figma export 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. --------- Co-authored-by: Quang Tran <16215255+trmquang93@users.noreply.github.com>
1 parent 9f6a759 commit 11fecef

57 files changed

Lines changed: 64162 additions & 54 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const browserGlobals = {
2626
TextEncoder: "readonly",
2727
TextDecoder: "readonly",
2828
crypto: "readonly",
29+
ClipboardItem: "readonly",
2930
KeyboardEvent: "readonly",
3031
MouseEvent: "readonly",
3132
CustomEvent: "readonly",

figma-plugin/reference-clipboard.html

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)