Export and Handoff
How to export designs and generate handoff documentation for developers converting prototypes to production code.
Other export actions
SVG:
export-svgexports a design project as an SVG document (aforeignObjectwrapper around the standalone HTML), giving agent parity with the editor's Download SVG command. The editor's own Download SVG command captures the live browser DOM for the most faithful snapshot; use the action when you need agent-side SVG export without a live browser. This is not importable into Figma as editable vectors — Figma cannot parseforeignObjectcontent, so it stays an opaque embedded HTML blob. Useexport-design-as-figma-svg(below) when the destination is Figma.PNG:
export-pngrenders one stored HTML screen in headless Chromium and uploads the PNG through the configured file provider. PassfileId, ordesignIdplusfilename, to select the screen. It returns a durableurland suggestedfilename;widthdefaults to 1440px andheightonly sets the responsive viewport because the export includes the screen's full page.pnpm action export-png --designId <designId> --fileId <fileId>If Chromium or file storage is unavailable, the action returns an explicit failure instead of pretending that a downloadable image exists. The editor's Download PNG remains the faithful client-side path for localhost/fusion screens that are not stored HTML.
Deploy preview:
deploy-design-previewtriggers a preview deploy for a fusion-backed design branch. It requires the design's source to advertise thedeployPreviewcapability (fusion tier) and Builder.io to be connected; a branch must already exist viacreate-design-branch. For inline/localhost designs it returnsctaRequired: truewith a Make-it-real CTA instead of faking a deploy. This triggers a preview deploy only — production publishing goes through the Builder Visual Editor's Publish flow.
Export Formats
HTML Export
Bundles all design files into a single standalone HTML file with Tailwind CSS and Alpine.js CDN included.
pnpm action export-html --id <designId>
Returns:
html— the complete HTML stringfilename— suggested filename (e.g.,SaaS-Landing-Page-1714500000.html)filePath— saved todata/exports/fileCount— number of source files bundled
The exported HTML:
- Includes
@tailwindcss/browser@4andalpinejs@3.15.11CDN links - Combines all CSS files into a single
<style>block - Combines all HTML/JSX files into the
<body> - Works when double-clicked in any modern browser
ZIP Export
Creates a ZIP archive with all design files organized by type plus metadata.
pnpm action export-zip --id <designId>
Returns:
zipBase64— base64-encoded ZIP datafilename— suggested filenamefilePath— saved todata/exports/fileCount— number of files included
ZIP structure:
project-name/
README.md # Project metadata
html/ # HTML files
index.html
components.html
css/ # CSS files
styles.css
jsx/ # JSX files (if any)
assets/ # Asset files
design-data.json # Generation metadata
PDF Export
Prepares design data for client-side PDF rendering. Returns the raw design data and files — the actual PDF generation happens in the browser.
pnpm action export-pdf --id <designId>
Returns all design data and files needed for the client to render a PDF.
Export to Figma (SVG)
export-design-as-figma-svg exports a design screen (or a selected
element's subtree) as a genuinely VECTOR SVG document — real
<rect>/<path>/<text>/<image> markup with
<linearGradient>/<radialGradient>/<filter> defs. Figma's SVG importer
parses this into normal, editable layers (rect/path/gradients/filters stay
editable). This is a different artifact from export-svg above, whose
foreignObject wrapper Figma cannot import as vectors at all.
pnpm action export-design-as-figma-svg --designId <designId>
Optional args:
fileId/filename— pick a specific screen (defaults toindex.html).nodeId— scope the export to one selected element's subtree via itsdata-agent-native-node-id, instead of the whole screen.embedImages(defaulttrue) — fetch and inlinehttp(s)image sources and background-images asdata:URIs, so the SVG is self-contained for clipboard paste. Setfalseto keep absolute URLs instead.
Returns { svg, filename, report, filePath? }. report classifies every
element as vectorized, approximated (mapped with a documented caveat —
e.g. a non-square gradient angle, a non-uniform border, a radial gradient's
shape/position), rasterized (video/canvas/iframe content, and any element
with backdrop-filter, which SVG cannot express — embedded as a cropped
screenshot instead), or omitted. If no headless Chromium binary is
available in the current environment (expected in hosted/serverless
deploys), the action returns { ok: false, reason } instead of throwing —
fall back to export-svg or export-html.
Vectorized-text caveat: Figma imports SVG <text> as live, editable
type, but its SVG importer reads only font family, size and a coarse bold
weight. Letter spacing is dropped, and weights above 700 resolve to Bold,
so tracked or extra-bold text arrives at a different width than the design.
Measured against Figma directly: textLength/lengthAdjust, multi-value
and sibling tspan x, word-spacing and family-encoded weights are
ignored too. Everything else in the document is geometry-exact. This is a
Figma import limitation, not a defect in the export; the report's
vectorizedTextCaveat field carries this note for the agent/user.
Getting it into Figma: two supported paths —
- Copy, then paste into Figma. In the editor, right-click a selected
element or the canvas and choose Copy as SVG (Copy/Paste as ▸ Copy as
SVG). This writes the SVG markup to the system clipboard as
text/plain(the MIME Figma's own paste handler reads for "paste as vector shapes") plusimage/svg+xmlas a secondary representation. Paste directly into a Figma canvas. - Download, then drag-import. Figma's file browser also accepts a
plain
.svgfile dropped/imported directly — save thesvgstring returned by the action to a.svgfile and drag it into a Figma page the same way you'd import any other SVG asset.
Coding Handoff
When a user wants to convert an Alpine.js + Tailwind prototype into production
code, use the canonical export-coding-handoff action instead of hand-writing
a handoff message:
pnpm action export-coding-handoff --id <designId>
This returns tokenized raw and ZIP URLs any external coding agent can fetch,
plus a ready-to-copy prompt. The bundle reflects the design's current
state — live editor (collab) content plus the user's applied visual tweaks
resolved into the HTML :root — so the generated code matches what the user
actually tuned, not the original generated tokens. Pass format: "json" if the
receiving agent wants structured data instead of markdown, and origin to get
an absolute raw-code URL for a specific app origin. This is the canonical
design-to-code tool; prefer it over composing a handoff message by hand.
Manual handoff template (fallback)
Use the template below only when export-coding-handoff isn't available or
the user explicitly wants a hand-composed summary instead of the action's
bundle. Compose it based on the design's actual HTML/tokens.
Handoff Prompt Template
## Design Handoff: [Project Title]
### Design Tokens
```css
:root {
--color-primary: [value];
--color-accent: [value];
--color-surface: [value];
--color-text: [value];
--color-text-muted: [value];
--font-heading: [value];
--font-body: [value];
--radius: [value];
}
Typography
- Heading font: [Font Name] (Google Fonts)
- Body font: [Font Name] (Google Fonts)
- Heading sizes: H1=[value], H2=[value], H3=[value]
- Body size: [value]
- Weight: Heading=[value], Body=[value]
Color Palette
| Token | Value | Usage |
|---|---|---|
| Primary | [hex] | Page background |
| Accent | [hex] | CTAs, active states |
| Surface | [hex] | Cards, panels |
| Text | [hex] | Primary text |
| Text Muted | [hex] | Secondary text |
Interactive States
List all Alpine.js state variables and what they control:
mobileNav: boolean— Mobile navigation toggleactiveTab: string— Tab switching ("overview" | "analytics" | "settings")filter: string— Filter control ("all" | "design" | "code")modalOpen: boolean— Modal visibility
Responsive Breakpoints
| Breakpoint | Width | Key Changes |
|---|---|---|
| Mobile | < 640px | Stacked layout, hamburger menu |
| Tablet | >= 768px | 2-column grid, sidebar hidden |
| Desktop | >= 1024px | Full layout with sidebar |
| Wide | >= 1280px | Expanded content area |
Component Inventory
List every distinct component in the design:
- Navigation — Fixed header with desktop links + mobile hamburger
- Hero Section — Full-width, centered text, dual CTAs
- Feature Card — Icon + title + description in a surface card
- Stat Card — Metric value + change indicator
- Data Table — Header + rows with status badges
- Footer — Links + copyright
Accessibility Notes
- All interactive elements have
cursor-pointer - Mobile touch targets >= 44x44px
- Color contrast meets WCAG AA
- Semantic HTML structure (nav, main, section, footer)
- ARIA labels on icon-only buttons
Source Files
The prototype HTML is available via:
pnpm action export-html --id [designId]
### Generating the Handoff
When the user asks to "hand off" or "convert to production code", call
`export-coding-handoff --id <designId>` first (see Coding Handoff above) — it
already extracts tokens, resolves applied tweaks, and returns a ready-to-copy
prompt plus fetchable URLs. Only fall back to composing the manual template
by hand if that action is unavailable:
1. Read the design: `get-design --id <designId>`
2. Extract all CSS custom properties from the HTML
3. Identify all Alpine.js state variables and their purposes
4. List all interactive components and their behaviors
5. Note responsive breakpoints and layout changes
6. Compose the handoff prompt using the template above
7. Optionally export the HTML: `export-html --id <designId>`
### Framework-Specific Recommendations
Include recommendations for the target framework:
**React / Next.js:**
- Replace `x-data` state with `useState` or Zustand
- Replace `x-show` with conditional rendering (`{condition && <Component />}`)
- Replace `x-for` with `.map()`
- Replace `@click` with `onClick`
- Replace CSS custom properties with CSS Modules or Tailwind config
- Replace Google Fonts CDN with `next/font`
**Vue:**
- Replace `x-data` with `ref()` / `reactive()` in `<script setup>`
- Replace `x-show` with `v-show`
- Replace `x-for` with `v-for`
- Replace `@click` stays the same (`@click`)
- Alpine.js and Vue share similar template syntax
**Svelte:**
- Replace `x-data` with `let` declarations
- Replace `x-show` with `{#if}` blocks
- Replace `x-for` with `{#each}` blocks
- Replace `@click` with `on:click`
## Duplicate for Iteration
Before exporting or handing off, the user may want to duplicate the design for further iteration:
```bash
pnpm action duplicate-design --id <designId> --title "Landing Page v2"
This creates a deep copy with new IDs for the design and all its files. The original stays untouched.