---
name: mockup-studio
description: >
  Turn a real app's UI into premium, pixel-accurate marketing graphics. The flow is two stages:
  (1) build an EXACT code mockup of the interface — render the running app when possible, otherwise
  re-author it faithfully in HTML/CSS (2D flat or 3D tilted) and screenshot it with a headless browser;
  (2) optionally pass that render to GPT Image 2 (edit mode) to add the premium finish — reflections,
  cinematic depth-of-field, lighting, glass, backgrounds/environments. GPT Image 2 is the ONLY finisher
  (called direct via the OpenAI API, never through Higgsfield). Includes a split-test MODE that pits Claude
  Fable against Claude Opus on the code step so you can pick the better frontend model. Use this whenever the
  user wants to "create a mockup",
  "mockup dashboard UI", "3D mockup", "hero shot of my app", "product marketing render", "make my UI look
  premium / expensive", "turn this screen into a graphic", "replicate this interface exactly", "onboarding
  flow mockup", "website hero from my app", "app store screenshots", "premium website assets", or to
  "split-test Fable vs Opus" on frontend. Trigger even if they don't name the tool — any request to turn a
  UI or a design reference into a polished image belongs here. This is GLOBAL: it works in any repo, and is
  designed to read a product's own source files so the mockup shows THAT product's real interface.
---

> **PORTABILITY NOTE (added 2026-07-27).** This process doc is published from Imperium's
> internal operating system. The METHOD is fully portable: prompts, model choices and
> parameters, CSS/SVG recipes, QA gates, and cost discipline all work anywhere. Paths that
> start with `~/.claude/`, `<repo-root>/`, `presentations/`, `scripts/`, or `memory/` are
> internal conveniences on the author's machine; substitute your own equivalents (any
> headless-browser screenshot loop, any image toolchain). Same for internal distribution
> steps (Google Drive folder IDs, Telegram bots) and `<your-vercel-team>` deploy scopes:
> use your own storage, messaging, and hosting. Working style anchors ship WITH this kit
> in `../cards/`, `../console/`, and `../folder/` — start from those, not from zero.

# Mockup Studio

Produce premium UI graphics from a real product's interface. Two stages, and the order is the whole point:

```
STAGE 1 — CODE (accuracy)          STAGE 2 — FINISH (premium, optional)
source of truth ──► exact ──► PNG  ──►  GPT Image 2 edit ──► hero image
(running app / code)  code    render     (reflections, DoF,     (curated)
                                          lighting, glass, env)
```

**Why this split.** Accuracy and photorealism pull against each other. Code owns accuracy and consistency
(deterministic, exact text, a real design system). Image models own photoreal richness but drift run-to-run.
So build the interface in code first, then use the image model only as a finishing filter on top. Never let
an image model invent the UI — it will hallucinate fonts, columns, and logos, and every render will differ.

**The consistency rule (important for product work).** The CODE render is the canonical, consistent asset —
ship that in-app or anywhere screens must match each other. The GPT Image 2 finish is a *per-hero art pass*:
its lighting/angle/reflections vary each run, so you curate the output. Do not use it for graphics that must
be visually consistent with each other; use the code render for those.

---

## Stage 1 — Build the exact code mockup

Accuracy here is everything. The finish can only ever be as faithful as the base. Climb this **fidelity
ladder** and use the highest rung you can reach:

1. **Render the running app (best).** If the product's repo runs, start its dev server, navigate to the
   exact screen, and screenshot the *real* UI. This is genuinely identical — no re-drawing. See
   `references/pipeline.md` → "Render the real app".
2. **Render real components in isolation.** If the whole app won't boot easily, mount the actual component(s)
   (Storybook, a scratch route, or importing the component into a tiny harness) and screenshot those. Still
   the product's real code, real fonts, real tokens.
3. **Re-author faithfully (fallback).** If neither is practical, rebuild the screen in standalone HTML/CSS.
   Pull the real fonts, colors, spacing, and copy from the source (`grep` the design tokens / Tailwind config
   / CSS variables). Hardcode exact visible text. This is what to do for a *design reference* (an image) too.

**Always verify against ground truth.** Screenshot your mockup and diff it by eye against the real screen (or
the reference image). Fix what's off, re-render, repeat. First drafts are ~80%; the compare→fix loop is what
gets you to identical. Watch the details that betray a fake: background gradient, font weight, icon geometry,
border hairlines, corner radii, shadow softness.

**2D vs 3D.** Flat (2D) for straight product screenshots. 3D tilt for hero shots — build the UI flat, then
wrap it in a CSS 3D transform. The reusable transforms, depth-of-field, and glass recipes are in
`references/css-3d-recipes.md`. Geometry (tilt/angle) MUST be set in code — the GPT finish preserves whatever
geometry you feed it and won't reliably re-tilt from a prompt.

**Rendering mechanics** (the browser has sharp edges — read `references/pipeline.md` for all of them):
- The Playwright MCP blocks `file://` — serve the folder over localhost (`node scripts/serve.mjs <dir> 8799`
  or `python -m http.server`) and open `http://localhost:8799/...`.
- Google Fonts is blocked in the sandbox — bundle the `.woff2` locally and `@font-face` it.
- Render at 2x for crisp output (`body { zoom: 2 }` + a 2x viewport), then screenshot.
- You can drive the screenshot via the Playwright MCP (no install) or `node scripts/screenshot.mjs <url> <w> <h> <out>` if Playwright is installed.

---

## Split-test mode — Fable vs Opus on the code step

Both Claude Fable and the current frontier Claude Opus model are strong at frontend. Which
reproduces a given UI more accurately is an empirical question — so test it on YOUR interfaces rather than
trust a leaderboard. **Run this as a MODE, not on every job** (it doubles cost/time); use it once to decide,
then default to the winner.

When the user asks to compare, or says "split-test", follow `references/split-test.md`:
1. Spawn two subagents in the same turn, one with `model: "fable"`, one with `model: "opus"`, each given the
   *same* brief + the same source/reference and the same instructions (inject full context — subagents start
   blank). Each returns a standalone HTML mockup.
2. Render both to PNG (same viewport).
3. Score both against the ground-truth screenshot on the rubric in `references/split-test.md` (text accuracy,
   layout precision, styling fidelity, detail polish, code cleanliness). Show both renders + the scores.
4. The user picks the winner; note it for future default runs.

---

## Stage 2 — The premium finish (GPT Image 2 — the ONLY finisher)

Once the code render is faithful, optionally elevate it. **The finisher is GPT Image 2, called DIRECTLY via
the OpenAI API (`edit` endpoint) — never through Higgsfield or any other service.** It processes reference
images at locked high fidelity, which is exactly why it preserves your layout, fonts, and text while adding
realism. Full params, sizes, costs, prompt recipes, and the tweak vocabulary (palettes, blur, framing,
shadows, backgrounds) are in `references/finishers.md`. The bundled script does it in one call:

```bash
# needs OPENAI_API_KEY (checks env, then ./.env, then the path in $ENV_FILE)
node scripts/gpt-finish.mjs \
  --image path/to/code-render.png \
  --out   path/to/hero.png \
  --preset premium-3d          # or: reflection | desk-scene | gradient-bg | glass | studio
  # or free-form:  --prompt "your finishing instruction"
```

Rules that keep the finish faithful (see `references/finishers.md`):
- Always use **edit** mode with the code render as the input image. Never pure text-to-image for product UI —
  it invents everything. (Pure gen is only for throwaway concept art.)
- Tell it explicitly to keep every element, icon, and string exactly and correctly spelled; add only the
  lighting/reflection/DoF/environment.
- It's **non-deterministic** — generate a few, pick the best. Long calls: use `quality: medium` and retries
  (the script handles this).

## Transparent (alpha) deliverables — Alex's preferred default for website assets

When the asset will sit on an unknown background (website sections, decks, any theme), deliver a
TRANSPARENT PNG instead of a baked backdrop (established 2026-07-05, Imperium HOME set):

- Render the CODE mockup with `scripts/screenshot-alpha.mjs <url> <w> <h> <out.png>` (Playwright
  `omitBackground: true`) and `body { background: transparent }` in the mockup.
- **GPT Image 2 cannot produce alpha** — verified live 2026-07-26: the API returns
  `Transparent background is not supported for this model` when `background=transparent` is passed,
  and matting a baked backdrop out afterwards leaves backdrop-tinted halos in the soft shadows.
  `gpt-image-1.5` DOES accept `background=transparent` (real alpha channel, soft-shadow partials
  included) but fails the identical-text bar even at `quality=high input_fidelity=high` — tested
  2026-07-26 on the due-diligence card: "Add item"→"Add itern", "Verify"→"Verfly", row IDs
  renumbered, card geometry invented. Do not use any image model for transparent UI assets. For transparent assets the
  premium finish is CSS-native, and it all lands in the alpha channel: layered box-shadows (tight
  contact + long ambient), a specular sweep overlay (diagonal white gradient, ~10–13% peak), glass
  titlebar gradients with an inset top highlight, a mint ring (`0 0 0 1px rgba(76,183,130,.14)`),
  and reflections as a mirrored clone of the window (`translateY(H) scaleY(-1)`, blurred ~1.5px,
  opacity ~.18, mask fading within ~25%, its box-shadows disabled).
- **HARD RULE: every top-level surface (window, card) must be fully opaque.** An rgba() top-level
  fill goes muddy on dark sites (found 2026-07-05: an 88%-white card darkened on dark backgrounds).
  Translucency is fine for surfaces INSIDE a window, over its solid base.
- **Verify:** composite the PNG onto 4 test backgrounds (near-black, white, brand color, grey) in a
  throwaway HTML and eyeball; confirm RGBA via the PNG header (`colorType=6`, byte offset 25).
- Optionally also ship a GPT-finished flat version for art-directed contexts; the alpha render is
  the canonical, flexible asset.

## Do NOT use Higgsfield (or any image model that isn't GPT Image 2) to finish stills

Tested and rejected 2026-07-03: Higgsfield's models reinterpret the UI — they garble text, invent columns,
and drop elements even when told to keep it identical. GPT Image 2 (direct OpenAI) is the ONLY finisher for
premium stills. Never route the finish through Higgsfield.

**Motion/animation** (a hero that moves) is out of scope for the still finisher and should stay **code-native**
— animate the live HTML/CSS mockup with GSAP or render it with Remotion. That keeps text crisp and
deterministic, the same reason code owns Stage 1.

---

## Quick routing

| User says | Do |
|---|---|
| "make a premium hero of my dashboard" | Stage 1 (render real app) → Stage 2 GPT finish |
| "replicate this screen exactly" (image given) | `references/pixel-replica.md` — the measured loop (shot.sh + pixel-compare.py + fit-gradient.py). Run it end-to-end in one turn |
| "which model builds my UI better" | Split-test mode |
| "make it 3D / tilted hero" | Stage 1 with `css-3d-recipes.md` → finish |
| "animate this" | code-native motion (GSAP on the mockup, or Remotion) — never Higgsfield |
| "app store screenshots / website assets" | Stage 1 at each screen → finish per hero |
| "change the background / palette / blur / shadow" | re-run finish with a tweaked `--prompt` (see `finishers.md` → Tweak vocabulary) |
| "transparent background / must work on any background" | Stage 1 alpha render (`screenshot-alpha.mjs`) + CSS-native finish — no GPT (it bakes the backdrop) |

## Files
- `references/pipeline.md` — end-to-end steps, rendering the real app, all browser gotchas, verify loop
- `references/pixel-replica.md` — pixel-perfect replication loop: measure-first, per-region diff scoring, Gaussian-lobe gradient fitting (proven 89.8% within-12 on the Revenue Flow card)
- `references/split-test.md` — Fable-vs-Opus protocol + scoring rubric
- `references/finishers.md` — GPT Image 2 params, prompt recipes, costs, and the tweak vocabulary
- `references/css-3d-recipes.md` — reusable 3D tilt, depth-of-field, glass, dot-grid, shadow
- `scripts/gpt-finish.mjs` — code render → GPT Image 2 edit → hero PNG
- `scripts/screenshot.mjs` — URL → PNG (Playwright, if installed)
- `scripts/screenshot-alpha.mjs` — URL → transparent PNG (Playwright `omitBackground`, for alpha deliverables)
- `scripts/serve.mjs` — tiny static server for local rendering
- `scripts/shot.sh` — local HTML → exact-size PNG via chrome-headless-shell (full Chrome hangs on this Mac)
- `scripts/pixel-compare.py` — render vs reference: score, worst cells, diff-heat + side-by-side
- `scripts/fit-gradient.py` — fit any complex background as rotated Gaussian light lobes → CSS (plus-lighter)
