01The brief
Grant based the prompt on the one Nick Saraev used for the Fable 5 website factory. Grant changed one thing: instead of random fictional sites, every page had to sell a real product he runs. The core of it:
“Each landing page fundamentally different… high-quality 3D, otherworldly animations, exceptional color palettes, novel font styles… Before you ‘ok’ each site, do at least three iteration passes.”
Real products change the job. A fictional site can say anything; a real one has pricing that must match, claims that must be true, a pilot school that must never be named, and a legal disclaimer that has to appear word for word. The beautiful part was the easy part. Keeping 26 pages honest took most of the planning.
02The system
One orchestrator session (me) did the planning, the shared tooling, the safety review and the deploy. Thirteen builder agents, each also Opus 5.5, did the pages: one agent per product, two pages each, so an agent could deliberately make its two variants disagree. All of them ran at once.
The builders ran for 28 to 51 minutes each. Because they ran concurrently, the whole collection took about an hour of build time, plus about half an hour of set-up and an hour of review and deploy.
03Research every product first
Before any design, a research agent read each product's repo and docs: READMEs, PRDs, brand kits, live copy, pricing pages. It came back with a one-page brief per product: what it is, who it's for, real features in the product's own words, real pricing and CTAs, brand colours and fonts, usable brand files, and a “keep off the page” list.
That last list mattered more than anything else. It flagged dashboard counters with no source behind them, a leaderboard of placeholder names on a live site, a pilot school that must never be named, a day-job employer that must never appear, products that aren't live yet, and a “no data leaves your device” claim that isn't true for the hosted version. Each became a hard rule in that product's brief.
04Art-direct all 26 at once
If you ask thirteen agents separately for “something stunning”, you get thirteen dark pages with a glowing orb. So every direction was written centrally in one pass, as a matrix, checked for collisions across the whole set:
- Light vs dark balanced across the collection (roughly half each).
- One signature technique per page, with no repeats: a scroll-scrubbed film, a self-drawing exploded view, a curved video wall, a DOM page-curl, a glass cube of words, a physics bin, a talking blob, a flocking squadron, a riso shader, a soft-body jelly logo…
- Variant A usually honours the existing brand; variant B reinterprets it. Where the brand forbids something (Sage: light mode only, 18px minimum text, gentle motion), both variants obey.
- Collisions were caught at this stage. An early plan had two night-time 3D cities; one became a film instead.
Each direction was one dense paragraph: concept, signature moment, palette intent, type intent. Builders were told it was “a strong starting point, not a cage”. Several found better ideas and took them. The magazine page's WebGL page-curl became a pure-DOM fold, which made it sharper and fully accessible.
05Moodboards from Pinterest
For each of the 26 directions I ran one Pinterest search in a real, logged-in browser session (a shared Chrome driven over the Playwright MCP). The script collected the top pins and saved six per direction: 144 references in all, kept out of the published site.
Builders used them two ways. They read them as a moodboard, and they passed a few as style references to GPT Image 2's edit endpoint, with a prompt describing a completely new subject. The result keeps the lighting, grain and palette of the reference and none of its content. About half of all generated stills went through that route.
06Generate the assets
Every image and video on the 26 pages was generated for them, apart from each product's real logos and a few pieces of real brand art. All generation went through one tiny script, fal.py (Python standard library only), which calls fal.ai and logs every prompt:
# a still (GPT Image 2 via fal.ai)
python3 tools/fal.py image --size 1920x1088 --quality high \
--prompt "Cinematic low-angle macro of a matte graphite keyboard at night…" \
--out _raw/gtalk/a-keys.png
# same, but steered by two Pinterest pins as style references
python3 tools/fal.py image --ref refs/gtalk/b-pin2.jpg --ref refs/gtalk/b-pin5.jpg --prompt "…" --out …
# animate the still (Veo 3.1 fast, 1080p, no audio)
python3 tools/fal.py video --image _raw/gtalk/a-keys.png --duration 6 \
--prompt "Locked-off camera, extremely slow push-in, violet underglow breathes…" --out _raw/gtalk/a-keys.mp4
# ship only optimized files
python3 tools/fal.py optimize-image in.png page/media/x.webp --width 2000 --q 80
python3 tools/fal.py optimize-video in.mp4 page/media/x --width 1280 # → x.mp4 + x.jpg poster
What made the assets look expensive
- Prompt like a cinematographer. Lens, angle, light source, colour of the light, where the negative space goes (“lots of empty dark space in the upper half” leaves room for the headline).
- Ask for motion that loops. “Locked-off camera, slow drift, nothing enters or leaves frame.” Even then most Veo clips had a visible seam, so builders trimmed and ping-ponged them (forward + reverse) with ffmpeg. That hides the seam completely.
- Grade after generating. A clip that drifted magenta got a hue shift in ffmpeg. The Night Shift film is graded live in a WebGL shader, black-and-white with only warm light kept, turned brand orange.
- Keep type out of images. Generated text is unreliable; every word on every page is real HTML.
- Budget. At most 2 clips per page and about 8 images. Pages landed between 0.7 and 4.1 MB of media. The whole collection cost roughly $60 in fal.ai credits (≈$30 images, ≈$30 video).
07Build in parallel
Every builder got the same binding spec (read it here) plus its product brief. The spec did the heavy lifting:
- Plain static HTML/CSS/JS, no build step. Each page is a folder:
/product/variant/index.htmlplus its ownmedia/. - One shared, audited library folder. three.js r185, GSAP 3.15 (all plugins), Lenis and matter-js, pinned and self-hosted. No other CDNs, analytics or third-party requests; Google Fonts was the only exception.
- Content rules: real facts only, honest labels (“Illustrative”, “Sample”, “at launch”), waitlist forms that submit nowhere, and a banned-phrase list against AI-slop copy.
- Craft rules: a signature moment, a non-default type pairing, responsive down to 390px, DPR capped around 1.75, render loops that pause off-screen, full
prefers-reduced-motionversions, AA contrast, zero console errors. - A hand-back format, so 13 reports came back in one shape and this guide could be assembled from them.
08Three passes per page, with eyes
“Iterate” means nothing unless the model can see the page. Every pass started with shoot.cjs: a small Playwright script that loads the page in real Chromium (WebGL included), scrolls it one viewport at a time so scroll-triggered animation actually fires, saves screenshots at 1440px and 390px, and prints console errors, failed requests, horizontal overflow and load time as JSON.
node tools/shoot.cjs http://localhost:8555/gtalk/ink-from-air/ /tmp/gtalk-b-p2 --frames 6 --mobile
# → 12 screenshots + {"errors":[],"failed":[],"overflowX":false,"loadMs":412}
The builder looked at every screenshot, wrote down what was wrong, fixed it, and captured again to confirm. Each pass had a different focus, and they were never merged:
- Design and hierarchy. Composition, type rhythm, colour, contrast, whether the signature moment actually lands, copy quality. This pass made the biggest visual jumps.
- Mobile, motion and accessibility. 390px layouts, touch, reduced motion, focus, screen-reader behaviour, animation timing.
- Performance and technical. Console, 404s, media weight, off-screen pausing, lazy-loading, meta and og tags, final details.
Every pass is logged, with what was found and what changed. The one-line summaries are in the catalogue below.
09Safety checks
Grant asked for two things: check third-party code before using it, and check everything before it goes on his server.
Third-party code
- Libraries were installed from npm with install scripts disabled, then
npm audit signaturesverified registry signatures (4/4) andnpm auditfound 0 vulnerabilities. - Versions were pinned to releases at least several weeks old: three.js 0.185.1 rather than the two-week-old 0.186.
- The vendored files were grepped for
eval,new Function, cookies, beacons, WebSockets and hard-coded hosts. The only URLs were documentation links in comments. - Pinterest pins are images, only ever viewed as references. No third-party code or prompts from them were used.
Before deploy
- All 26 pages were grepped for external hosts. The only ones are Google Fonts and each product's own domain. No trackers, no iframes, and no form posts anywhere.
- They were also grepped for secret-shaped strings (API keys, tokens) and every name on the “keep off the page” lists. Clean.
- A human-language pass: one page described the real nurse Call Helper was built for with gendered pronouns. It was rewritten neutrally, because the person is real and I don't know their pronouns.
- The container is
nginx:alpineserving static files withnosniff, a referrer policy, a frames policy, and camera, mic and location disabled. Raw assets, references and tools are excluded from the image.
10Deploy
The whole collection is one static site in one private GitHub repo, deployed by Coolify from a two-line Dockerfile:
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY . /usr/share/nginx/html
Two details save a failed deploy. Nginx listens on both 80 and [::]:80, because the platform's healthcheck calls localhost, which resolves to IPv6 first. And absolute_redirect off keeps nginx's trailing-slash redirects on the public https host instead of the container's internal port.
The final pre-deploy check caught one more: nginx drops server-level add_header lines in any location that sets its own header, so the security headers were silently missing until they were repeated inside each location block. A curl -I against the locally built image showed it.
11What the passes caught
The passes paid for themselves. A few of the things that looked fine in code and wrong on screen:
- Film frames rendered upside down (WebGL texture origin). A reviewer reading code would miss it; a screenshot doesn't.
- A “fallback” still sat on top of the live 3D scene, so the clay diorama was invisible. Same bug, different page: a hidden fallback image covering the holographic card.
- Chrome won't blend a video into the page with
mix-blend-modein some stacking contexts; the faucet video showed as a white box. Fix: bake the paper colour into the video itself. - A phone layout that was secretly 672px wide, pushing a button off-screen at 390px.
- Glow that ate the text. The open chrome core blew the screen out to white-cyan, and the ink-bleed effect erased the thin strokes of a Bodoni headline.
- A mini-game that was too hard for five-year-olds. The builder played it and caught 0 stars in 10 seconds, then made it easier.
- Double downloads. Stickers, foil textures and posters were loading twice;
shape-outsideforced five “lazy” engravings (≈700 KB) to load up front. - Screen readers narrating autoplay demos every few seconds. Live regions now only announce what the visitor asked for.
- Reduced motion that hid content. Several pages had copy that only became visible via an animation. The reduced-motion versions now show everything.
12Do it yourself
The workflow doesn't depend on this repo. The minimum version:
- Write the briefs first. One page per product, with a “keep off the page” list. Real facts only.
- Write every art direction in one sitting, as a matrix, so nothing repeats. Give each page a single signature moment.
- Build the shared kit once. Pinned, audited libraries; an asset script; a screenshot script; one spec file every builder must follow.
- Launch one builder per product, in parallel, each doing both variants and all three passes against real screenshots.
- Review centrally, then ship one static site. Audit, thumbnail, write the guide from the pass logs, deploy.
The files used here, with local paths removed:
13All 26, page by page
Concept, palette, signature techniques, and a one-line summary of each critique pass. Open any row.