01 · Architecture
One orchestrator,
sixteen builders
The run is a tree, not a loop. A single orchestrator agent owns taste and coordination: it writes the creative briefs, locks the design-token registry, scaffolds the monorepo, and then launches one builder agent per site as parallel background workers — up to eight concurrent. Each builder gets a prompt with its brief, its claims, a binding contract, and a hard territory: its own sites/NN-slug/ directory and nothing else.
The monorepo uses npm workspaces with heavy dependencies hoisted once at the root — three, gsap, lenis, matter-js, postprocessing, vite, playwright, sharp. Builders are forbidden from running npm install; if a builder genuinely needs a new dependency it writes the need to a flag file and works around it meanwhile. This single rule eliminated every class of concurrent-install corruption.
# the shape of the repo
repo/
├── BRIEFS.md # 16 locked creative briefs
├── DESIGN-TOKENS.md # uniqueness registry (fonts/palettes/techniques)
├── docs/CONVENTIONS.md # the binding builder contract
├── shared/urls.json # live URLs, single source of truth
├── tools/ # screenshot.mjs · optimg.mjs · getfont.mjs · genimage.mjs
├── sites/01-… 15-… # one territory per builder
└── hub/ # this site — built last
Every site is an identical two-page Vite build (/ and /guide) on a deterministic dev port (4300 + site number). Identical skeletons mean one QA tool, one deploy command, and no per-site surprises — all the variance budget is spent where it matters, on design.
02 · Briefs & uniqueness
Convergence is the failure mode
Generated design drifts toward the mean: the same grotesque, the same near-black, the same hero-features-CTA scaffold. The countermeasure here was structural, not aspirational — two documents written before any code:
- Locked briefs. Each site got a full creative brief: concept, structure section-by-section, one signature moment, motion grammar, asset list, and the angle its own guide should take. Builders execute the brief; they don't reinvent it mid-build.
- A uniqueness registry. One table claims every display face, dominant palette, and signature technique. No two sites may share any of the three. Builders may refine within a claim, never drift into a neighbor's.
# DESIGN-TOKENS.md — two rows of the registry
| 04 | faultline-type | Anybody (var) / Space Mono | bone #EDE8DF, ink #111 → red #FF2B06 | kinetic variable type |
| 12 | cinder-tasting | Prata / Hanken Grotesk | char #191412, bone #EFE6DA → ember | candle-reveal menu |
The registry is why an index of fifteen sites reads like an exhibition instead of a template with fifteen skins. If you adopt one idea from this page, adopt this one.
03 · The contract
Rules the builders
couldn't break
A single CONVENTIONS.md bound every builder. The load-bearing clauses:
- Territory. Write only inside your own site directory. Never touch tools, root configs, or other sites.
- Readiness flag. Both routes must set
window.__READY = trueonce the hero settles — the QA harness waits for it, which makes screenshots deterministic even with load choreography. Always pair it with a timeout fallback so a broken timeline can't hang QA. - The /guide route. Every site ships a technical guide in its own aesthetic: concept, type/palette specimen, the signature technique with a real code excerpt, the asset prompts, and an honest iteration diary.
- Design floor. No system fonts, no lorem, body text ≥16px, real heading hierarchy, visible focus styles,
prefers-reduced-motionhonored, mobile as a first-class layout. - Weight ceiling. Nothing over 500KB ships in
public/; generation masters stay in an unshippedassets-src/.
Why a contract beats supervision: with eight agents running concurrently, per-decision review is impossible. A short binding document that every agent reads first replaces a thousand corrections. The contract is also what makes the run reproducible by other people — it's the interface.
04 · QA harness
Agents must see
their own work
The single highest-leverage tool in the run: a ~200-line Playwright script every builder ran after every build. It serves the site's dist/ on the site's own port, waits for window.__READY, and captures both routes at 375, 768 and 1440px — viewport crops and full-page — while recording every console message, failed request, and horizontal-overflow measurement into qa/qa-report.json. The builder then reads the images and acts on what it sees.
// the part everyone gets wrong: headless WebGL
const browser = await chromium.launch({
args: [
'--use-gl=angle',
'--use-angle=swiftshader',
'--enable-unsafe-swiftshader', // without this, WebGL2 contexts fail silently
],
})
// …wait for the page's own readiness signal, not networkidle:
await page.waitForFunction(() => window.__READY === true, { timeout: 15000 })
Hard-won harness rules:
- Software GL renders slowly and imperfectly — a blank canvas with zero console errors means "verify on a real GPU," not "rewrite working code." Builders wrote a
NEEDS-GPU-CHECKflag instead of thrashing; the orchestrator verified those six sites in real Chrome at the end. All six were fine. - Full-page captures taller than ~8192px crash SwiftShader, and Chromium then blocks WebGL for the whole origin — making every later screenshot lie. Keep routes under ~8000px or use viewport/scroll-step captures for tall pages.
- Scroll-step mode (one viewport at a time) is the source of truth for ScrollTrigger-pinned choreography; full-page captures of pinned sections are meaningless.
05 · Image pipeline
Photography
on demand
Nine of the fifteen sites use AI imagery; six deliberately use none (pure typography, generative canvas, physics, or shader work — range is part of the argument). The pipeline, at roughly 2 credits per image and ≈90 credits across the whole set:
| Model | Used for | Examples in the set |
|---|---|---|
| nano_banana_pro | Plates, product, set photography, 4K detail, text-in-image | Séance bottles · solar plates · botanical etchings · museum artifacts · chiaroscuro dishes |
| soul_2 | People — editorial, portrait, fashion | Crew portraits · glitch artist IDs · dune lookbook · guide portraits |
| marketing_studio_image | Product-forward compositions | Synth lifestyle shot |
- Series consistency comes from reference-media chaining: generate the first image, then pass it as a reference for the rest of the series (same bottle, same house, same model). Art-direct the prompt hard — one light temperature, one backdrop, one lens.
- Masters never ship. PNG originals stay in
assets-src/; a one-line sharp script exports ≤500KB responsive webp pairs intopublic/images/. - Fonts are assets too: a downloader tool fetches Google/Fontshare CSS, rewrites it, and self-hosts the woff2 files — no third-party font requests on any of the sixteen sites.
06 · Iteration
Three passes,
logged honestly
Every site ran the same loop after its first build, and logged each pass in an ITERATION-LOG.md:
- Structure. Every section present on both routes, real copy, images in place, fonts loading, sound layout at all three widths.
- Craft. Motion polish, spacing rhythm, typographic detail, zero console errors, kill every horizontal overflow.
- Complexify & refine. Re-enter as a hostile critic: find the weakest screen and elevate it; add the detail that makes the page unforgettable; re-verify everything.
Pass 3 is where the signature moments sharpened — the seismic wave that propagates from the cursor, the candle that sways with scroll, the plumb-line bead. The passes exist because a first build is always adequate and adequate is the enemy. After all fifteen logs closed, the orchestrator did an art-director review of every site in real-GPU Chrome; it found exactly one live defect (an overlapping HUD chip at 1440px), which was fixed and re-verified the same hour.
07 · Resilience
The run broke twice
and didn't care
Mid-run, a network drop killed four builder agents; later, a monthly spend limit killed all eight active ones. No work was lost either time, because the architecture assumes interruption:
- Disk is the state. Builders write everything as they go — code, screenshots, QA reports, iteration logs. A killed agent's progress is fully legible from its directory.
- A completion rubric, not memory, decides where to resume: logs closed? QA clean and newer than the last source edit? Both routes shot at three widths? Resume at the first unmet criterion.
- Resumable agents. Revived builders got the same prompt template plus a "here is what exists on disk, continue from pass N" paragraph. One agent whose transcript was lost entirely was replaced by a takeover agent that finished passes 2–3 from the disk state alone.
08 · Deploy
Sixteen subdomains
# one-time, per project
npx wrangler pages project create seance-parfums --production-branch=main
# every deploy
npx wrangler pages deploy sites/01-seance-parfums/dist \
--project-name=seance-parfums --branch=main --commit-dirty=true
- Cloudflare Pages resolves
/guide→guide/index.htmlnatively — the two-page Vite build needs no redirect config. - First-deploy SSL can take a few minutes; curl both routes until 200 before announcing anything.
- Names are global. One project (
atelier-meridian) collided with a name in someone else's account and landed atatelier-meridian-cbe.pages.dev. Keep a singleshared/urls.jsonas the source of truth and build every cross-link from it — the collision then costs one JSON edit, not a link hunt. - The only human action in the entire run:
wrangler login.
09 · Takeaways
Steal this
- Lock taste before parallelism. Briefs and a uniqueness registry first; agents second. Diversity must be structural.
- Contracts over supervision. One binding conventions doc replaces continuous review at 8× concurrency.
- Give agents eyes. A screenshot harness the agent runs and reads is worth more than any amount of prompt exhortation about quality.
- Make readiness explicit.
window.__READYturns flaky visual QA into a deterministic wait. - Mandate iteration counts. "Three passes, logged" produces measurably better work than "make it great."
- Know your renderer's lies. Software GL under-renders and crashes on tall captures — classify before you "fix."
- Design for interruption. Disk-legible state plus a completion rubric makes any agent resumable by any other agent.
- Spend variance on design, not plumbing. Identical skeletons, wildly different souls.
10 · Go deeper
The fifteen guides
Every site documents its own signature technique with real code — the thin-film shader math, the per-glyph seismic engine, the FFT-to-shader plumbing, the sky's scattering ramp. These are the chapters of this book:
11 · Colophon
This hub, briefly
Concept. The exhibition itself: a near-black gallery whose index cards are fifteen hand-made miniatures — not screenshots — each rebuilt from its site's palette, typographic voice, and a hint of its signature motion. Built last, with full knowledge of the finished work.
Clash Display
Switzer carries the body — light, wide-set, unhurried. Two families, self-hosted, under 260KB of woff2 for the whole page.
Signature technique — the infection. Hovering any card makes the whole hub wear that site's identity: accent, selection color, cursor tint, and a page background mixed from the site's dominant. It's two CSS custom properties and one honest trick — never let the infected background get light enough to break contrast:
/* the page tints toward the hovered site, but never leaves the dark */
body.infected {
--page-bg: color-mix(in oklab, var(--infect) 14%, var(--void));
}
// JS on card hover: two properties, nothing else
root.style.setProperty('--accent', card:--site-a)
root.style.setProperty('--infect', card:--site-bg)
Assets. Zero generated images. The fifteen palettes are the artwork; the two living canvases (a seeded flow field for №05, a rippling dot terrain for №09) are drawn in 2D canvas at hover time. First load ships under the 1.5MB budget.
Iteration diary. Pass 1 caught two structural bugs its own harness exposed: CSS scroll-behavior:smooth raced the QA rig's programmatic scroll reset (the mobile hero captured mid-glide as pure black — smoothing moved to JS, user gestures only), and inline wrapper spans let three miniatures' eyebrows and titles flow onto one line. Pass 2 was craft on the weakest vignettes: №09's terrain re-tuned from stripes into rolling ridges, №01's separated blobs merged into one rotated smoke band, №10's artifacts seated on their plinths, №13's figure recut into a pleated gown silhouette, №11's spring redrawn as a coil with a dotted tether for the bouncing ball. Pass 3, as hostile critic, filled №02's dead corner with its catalog price ticket, then probe-verified the infection on both palette polarities (dark №07, light №08), confirmed reduced-motion leaves zero content hidden, and re-verified both routes at all three widths with a clean report.
Designed & built autonomously by Claude Fable 5 (Anthropic) — this hub included. Live at fable-fifteen.pages.dev.