# Pipeline — end to end

The full flow from a real product's UI (or a design reference) to a premium hero image.

## 0. Establish ground truth
Before building anything, get the target you must match:
- **Rebuilding a real screen** → a screenshot of the actual app screen (see "Render the real app").
- **From a design reference** (an image the user gave) → that image is the ground truth. Read it carefully
  and catalogue every element: exact strings, fonts, colors, icon shapes, spacing, selected/hover states,
  background, shadows.

## 1. Build the exact code mockup (fidelity ladder)

### Rung 1 — Render the real app (best, truly identical)
1. Find how the product runs: check `package.json` scripts (`dev`, `start`), README, or the framework
   (Next/Vite/CRA → a dev server; Electron/Tauri → a desktop shell that still renders a web view).
2. Start it (background), wait for the port, navigate to the exact screen/route.
   - Web app: open the dev URL in the Playwright MCP, navigate to the route, set the viewport, screenshot.
   - Needs auth/seed data: use a test account, a seeded fixture, or mock the data layer so the screen renders.
   - Electron/Tauri: run the renderer in a browser against the dev server if possible, or screenshot the app
     window. If truly not automatable, drop to rung 2.
3. Screenshot the real UI. Done — this is identical because it *is* the app.

### Rung 2 — Render real components in isolation
If the whole app won't boot: mount the actual component(s) via Storybook, a scratch route, or a tiny harness
that imports the real component with sample props. Screenshot that. Still the product's real code/fonts/tokens.

### Rung 3 — Re-author faithfully (fallback, and the path for design references)
Rebuild the screen in standalone HTML/CSS:
- Pull real design tokens from source: `grep` the Tailwind config, CSS variables, theme file, or component
  styles for the exact colors, radii, spacing, shadows, font stack.
- Get the real fonts. If they're licensed/local, reference them; otherwise bundle the closest web font
  (`.woff2`) locally. Match weight carefully — weight mismatches are a common tell.
- Hardcode exact visible text (including truncated strings like "…Sales P…") so truncation matches to the pixel.
- Rebuild icons as inline SVG.

## 2. Render your mockup to PNG (browser mechanics)
The headless browser has sharp edges — all handled here:
- **`file://` is blocked in the Playwright MCP.** Serve the folder: `node scripts/serve.mjs <dir> 8799`
  (or `python -m http.server 8799`), then open `http://localhost:8799/<file>.html`.
- **Google Fonts / external CDNs are blocked in the sandbox.** Download the `.woff2` and `@font-face` it from
  the same served folder. (Inter variable is a good SF-Pro substitute:
  `https://cdn.jsdelivr.net/npm/@fontsource-variable/inter@5/files/inter-latin-standard-normal.woff2`.)
- **Retina crispness:** author at native size with `body { zoom: 2 }` and set the viewport to 2× the design
  (e.g. design 680×540 → viewport 1360×1080). `zoom` re-lays out at higher density → crisp text (better than
  `transform: scale`, which blurs). Or screenshot with `scale: "device"`.
- **Screenshot:** via the Playwright MCP (`browser_navigate` → `browser_resize` → `browser_take_screenshot`)
  or `node scripts/screenshot.mjs <url> <w> <h> <out.png>`.

## 3. Verify against ground truth (the loop that gets you to 100%)
Screenshot your mockup, put it next to the real screen / reference, and diff by eye. First pass is ~80%.
Fix the tells and re-render. The usual offenders:
- background gradient / tint, font weight, icon geometry, hairline borders, corner radii, shadow softness,
  selected/hover row states, exact truncation points.
Repeat until you can't tell them apart. This loop is the difference between "vibe-coded" and "identical".

## 4. (Optional) Premium finish
Hand the faithful render to `scripts/gpt-finish.mjs` (see `finishers.md`). Remember: geometry/tilt must
already be right in the code render — the finish preserves geometry, it doesn't create it.

## Transparent (alpha) renders — mechanics
- `scripts/screenshot-alpha.mjs <url> <w> <h> <out.png>` = Playwright screenshot with
  `omitBackground: true`; the mockup's `body` must be `background: transparent`.
- Every TOP-LEVEL surface (window, card) must be a fully opaque fill — top-level rgba() whites go
  muddy on dark site backgrounds. Translucency only INSIDE a window over its solid base.
- The premium finish must be CSS-native (GPT bakes a backdrop): layered box-shadows, diagonal
  specular sweep (~10–13% white), glass titlebar gradient + inset top highlight, mint ring (`0 0 0 1px rgba(76,183,130,.14)`),
  mirrored/masked clone for the reflection (clone via a 3-line script, disable its shadows).
- Verify: composite onto near-black / white / brand color / grey in a throwaway HTML; check
  `colorType=6` (byte 25 of the PNG) for RGBA.

## Gotchas cheat-sheet
- `serve.mjs` on Windows Git Bash: pass a WINDOWS-style root (`C:\...`). A POSIX `/c/...` path
  resolves to `C:\c\...` inside Node — every request 404s and screenshots show just "not found".
- No Playwright install nearby? Junction one in: `cmd /c mklink /J <dir>\node_modules
  C:\...\some-repo\node_modules` (the VS Code fork repo has Playwright + Chromium already).
- `screenshot.mjs` renders at `deviceScaleFactor: 2` — author at design size, no `zoom` needed;
  the PNG comes out at 2× the viewport.
- Generated `*.png` may be gitignored in a repo (media kept out of git). Deliver via local `file://` paths;
  `git add -f` only if a repo copy is genuinely wanted.
- OpenAI edit calls are slow (~50-60s). Use `quality: medium` and retries (the script does).
- Screenshots from the Playwright MCP land in its output dir (often the repo root) — move them into your
  assets folder afterwards to keep the root tidy.
- Don't claim an image is "on GitHub" unless you actually committed it (watch for `*.png` ignore rules).
