Paper to GPUI
Turn a selected Paper design into maintainable GPUI code, then prove the native result against the design at the same viewport. Treat Paper as the visual contract and the current Rust checkout as the implementation contract.
Non-negotiable rules
- Inspect before editing. Verify the Paper file, selected node, GPUI version,
existing components, theme, assets, and dirty worktree first.
- Use Paper MCP evidence, not a screenshot alone. Capture hierarchy, computed
styles, text, fonts, assets, and a 2x screenshot of the exact target.
- Treat Paper JSX as a structural hint, never as GPUI code or unquestioned
truth. Computed styles and the screenshot settle ambiguity.
- Preserve the app shell, state model, component conventions, and platform
behavior. Replace only the visual surface in scope.
- Prefer GPUI layout over coordinate transcription. Use flex/grid for normal
structure and absolute positioning only where the design genuinely overlaps.
- Do not rasterize text, controls, panels, or whole screens to fake fidelity.
Export only real visual assets such as icons, illustrations, textures, and photos.
- Validate the native runtime.
cargo check is necessary but does not prove
fonts, window chrome, scale factor, focus, hover, clipping, or pixel fidelity.
- Work in small regions. Large artboards must be translated and compared
section by section before the whole screen is judged.
Workflow
1. Establish both contexts
Run the read-only project inspector:
scripts/inspect_gpui_project.sh /path/to/gpui-project
Then inspect the checkout directly:
- Confirm the repository root, branch, dirty state, and requested surface.
- Read the relevant
Cargo.toml, lockfile entry, app entrypoint, root view,
theme/tokens, reusable components, asset source, and nearby tests.
- Identify whether the project uses published
gpui, a Git revision, a
workspace checkout, a fork, or a wrapper component library.
- Follow the pinned checkout's APIs when they differ from examples. GPUI is
pre-1.0 and changes frequently.
Use the Paper MCP server:
- Call
getbasicinfo to verify the currently open file and artboards.
- Call
get_selection to resolve the target.
- If the selection is empty or includes unrelated nodes, ask the user to select
one artboard or frame. Do not guess from names when multiple targets fit.
- Default to read-only Paper tools. Do not change the design unless the user
explicitly asks for design edits.
Read [paper-mcp.md](references/paper-mcp.md) before extracting a non-trivial design or troubleshooting Paper connectivity.
2. Capture a design evidence pack
Acquire evidence in this order:
get_screenshot at 2x for the selected root.
getnodeinfo and gettreesummary for dimensions and hierarchy.
get_jsx for a compact structural interpretation.
getcomputedstyles in batches for the root, layout containers, text,
controls, separators, and visually distinct descendants.
getfontfamily_info for every non-system family and used weight/style.
getfillimage or export for real image/vector assets.
get_children plus targeted subtree calls when a large design exceeds tool
limits or loses detail.
Record a compact evidence table before coding:
| Paper node |
Role |
Bounds |
Layout |
Spacing |
Type |
Paint/effects |
Asset |
Behavior |
Include exact values where they affect fidelity. Do not fill unknowns with plausible defaults. Re-query the node or label the uncertainty.
3. Build a translation plan
Map the design into these layers:
- Window and chrome — viewport, titlebar, background, safe inset, minimum
size, and platform-specific frame.
- Structural regions — sidebar, toolbar, content columns, inspector, footer,
modal, or overlay.
- Reusable primitives — button, icon button, field, row, badge, separator,
list item, empty state, and section heading.
- Tokens — color, spacing, typography, radius, border, shadow, and
breakpoint constants.
- State and behavior — selection, hover, pressed, focus, disabled, loading,
scrolling, shortcuts, and resize behavior.
Reuse existing tokens and components when their rendered result matches. Extend them narrowly when they do not. Do not create a parallel design system for one screen.
Read [gpui-translation.md](references/gpui-translation.md) before implementing. It contains the detailed Paper/CSS-to-GPUI mapping and the boundaries where GPUI needs a custom element, canvas, or deliberate approximation.
4. Implement from geometry inward
Use this order because it minimizes rework:
- Match window/content bounds and large background regions.
- Match flex direction, fixed/flexible dimensions, gaps, padding, alignment,
wrapping, overflow, and clipping.
- Match typography: actual family, available weight, size, line height,
wrapping width, alignment, truncation, and baseline.
- Match fills, borders, radii, opacity, shadows, gradients, and separators.
- Add exported assets at their intended logical size.
- Add interaction states and focus behavior.
- Extract reusable GPUI components only after the repeated visual pattern is
confirmed.
Keep exact Paper pixels as px(...) during the first fidelity pass. Consolidate repeated values into project tokens after the screen matches. Avoid premature rounding to GPUI convenience scales such as .gap_3() when Paper specifies an off-scale value.
5. Validate behavior and visual fidelity
Run the nearest repository checks first:
cargo fmt --check
cargo check -p <owning-crate>
cargo test -p <owning-crate>
cargo clippy -p <owning-crate> --all-targets -- -D warnings
Adapt commands to the repository. Do not claim checks that were unavailable or unreasonably broad.
Then launch the real app and compare:
- Reproduce the Paper artboard's logical viewport inside the GPUI content area.
- Confirm OS scale factor, theme, font availability, and window chrome.
- Put the app in the same state and use the same content as Paper.
- Capture the GPUI window or content region without resizing the result.
- Compare side by side, overlay at partial opacity, and use a difference image
when tooling is available.
- Fix mismatches in this order: bounds, layout, typography, paint, assets,
interaction polish.
- Repeat until further changes are below the agreed tolerance.
Read [fidelity-validation.md](references/fidelity-validation.md) for capture normalization, diff techniques, tolerances, and mismatch diagnosis.
6. Prove completion
Do not call the work complete until:
- The exact Paper file and target node are identified.
- The relevant GPUI crate builds and targeted tests pass.
- The native app has been launched at least once.
- A final Paper screenshot and GPUI screenshot exist at matching logical bounds.
- Major structure, typography, colors, radii, and assets have been visually
compared.
- Hover, active, focus, scrolling, resizing, and keyboard behavior relevant to
the screen have been exercised.
- Remaining deltas and platform limitations are stated plainly.
Reference routing
- Read [paper-mcp.md](references/paper-mcp.md) for connection setup, safe tool
sequencing, node extraction, tokens, fonts, assets, and Paper failure modes.
- Read [gpui-translation.md](references/gpui-translation.md) for current GPUI
architecture, styling APIs, property mapping, components, assets, state, and version shields.
- Read [fidelity-validation.md](references/fidelity-validation.md) for the
screenshot loop, visual tolerances, diff workflow, responsive checks, and native acceptance.
- Read [worked-example.md](references/worked-example.md) when starting a new
translation or when Paper's JSX/CSS structure does not map cleanly to GPUI.
Failure shields
- If Paper tools are absent, stop and explain how to connect Paper Desktop MCP.
Do not reconstruct a design from memory.
- If Paper reports the wrong file, have the user open the intended file and call
getbasicinfo again.
- If no single target is selected, ask for a selection or an exact node ID.
- If a Paper subtree is huge, split by structural region and keep one screenshot
of the full target for global alignment.
- If an exact font is unavailable to GPUI, do not silently substitute it. Report
the missing family/weight, add or register the font if authorized, then recapture.
- If a Paper effect has no direct GPUI equivalent, preserve hierarchy and
interaction, implement the nearest maintainable native effect, and document the delta. Consider canvas or a custom Element only after ordinary GPUI styling is proven insufficient.
- If screenshots differ despite equal CSS-like values, inspect content bounds,
device scale, text metrics, default line height, border inclusion, and OS window chrome before nudging arbitrary pixels.
Final response
Report:
- Paper file, artboard/frame, and viewport used.
- GPUI files and reusable components changed.
- Assets and fonts added or reused.
- Build, test, launch, and screenshot checks performed.
- Remaining visual or behavioral deltas.
- Any assumptions that still require user confirmation.