Build a landing page from one image

The Studio's most complete output is not the bare effect — it is a whole landing page composed around it: masthead, feature trio, quote, call to action, all coloured from the image itself and paced against the assembly. One command produces it. This guide is the judgement that goes around that command.

node cli.mjs product.jpg --theme editorial --brief page.json --out landing.html

1 — Size the grid before anything else

Start with a dry run: --emit json writes no file and reports the grid, instance count, and a tier — ok (up to 60,000 instances, comfortable on anything), amber (to 200,000, fine on desktops), or red (beyond that, for audiences whose GPUs you know). Iterate --rows here until the tier matches your audience. With the default full-image faces, sharpness comes from the texture rather than the grid, so rows beyond about 256 rarely earn their cost.

node cli.mjs product.jpg --rows 144 --emit json

2 — Pick a voice

Three page voices are built in, and they are genuinely different designs, not colourways: editorial sets a serif masthead with airy spacing; technical is monospaced and gridded, with a live readout of the assembly fraction; poster runs condensed capitals over solid accent blocks. The examples page shows all three composed from the same image — pick by looking, not by name.

3 — Write the brief

--brief page.json carries the copy and imagery: headline, dek, tagline, a feature trio, an optional gallery and full-bleed band, the quote, the reveal caption, and the call to action. Every field is optional, and anything missing renders as a visible placeholder rather than being silently dropped — a themed page with placeholders is a to-do list you can see. Two rules the brief enforces on your behalf:

For one-off tweaks, shorthand flags such as --headline, --dek and --cta "Label=https://…" override the brief file without editing it.

4 — Steer the palette, if you must

By default the page's entire colour system is extracted from your image — quantized, derived in OKLCH, and held to WCAG AA by construction: body text at least 4.5:1, accent at least 3:1. Four flags steer it, and all four land upstream of that enforcement: --bg forces the background and re-derives everything around it, --scheme dark|light overrides what the image implies, --tint gives a tonal steer, and --accent injects a brand colour. A legible brand accent is used verbatim; an illegible one is moved as little as possible, and the page's own HTML comments record exactly what shifted and why. If you need different colours, use these flags or change the image — never hand-edit the generated values.

5 — Look before you ship

A clean exit code cannot tell you whether your headline survives the noise behind it. Probe the finished page:

node cli.mjs product.jpg --theme editorial --brief page.json \
  --probe 0,0.5,1 --probe-dir ./probes --out landing.html --force

This opens the page headlessly, scrolls the camera to each assembly fraction, waits for it to settle, and writes a screenshot per stop. Fraction 0 should read as scattered noise, fraction 1 as the recognisable image — and the frames near 0.5–0.7, peak chaos, are where text fails first. Open the PNGs and look. If a section is drowning, give it a different beat in the brief or lengthen the track with --scroll.

What you ship

The output is one self-contained HTML file: image embedded, styles inlined, no build step, no framework, and a single external request for the pinned three.js library. It honours prefers-reduced-motion, keeps working without WebGL, and reads as designed over the flat background alone. Host it anywhere that serves static files. If you would rather mount the effect inside a page you already have, that is the embedding guide.