recon.md — scouting live references and building a moodboard
Taste is not invented at the desk. Every director watches films before shooting one, and the
reflex table in taste.md only tells you what to avoid — recon tells you what is currently
alive. Two commands do the gathering; you do the reading. Both write into design/, both are
cheap, both are bounded: recon is a short pass at the top of phase 0, not a research project.
command
answers
A
node scripts/refscout.mjs
how do the best sites in this space actually work? — live sites, their real stack, their scroll mechanics, screenshots
B
node scripts/moodboard.mjs
what should this feel like? — palette, light, composition, type energy, texture
Run A when the brief has a mechanic question (direct register, "wow", scroll choreography).
Run B when the brief has a look question (any register with an undecided art direction).
Most briefs want both, in that order, ~5 minutes total. Skip either without guilt when the brief
already fixes that axis (existing brand book → skip B; "boring docs site" → skip A).
Both need playwright (npm i -D playwright && npx playwright install chromium). No API keys,
no logins, no paid services.
A. refscout — take the references apart
# harvest what is winning right now, profile it
node scripts/refscout.mjs --from awwwards --limit 8
# same, filtered by the gallery's own category or a text search
node scripts/refscout.mjs --from awwwards:scrolling --limit 6
node scripts/refscout.mjs --from awwwards --search "coffee" --limit 5
# or profile sites you already know / found with web_search
node scripts/refscout.mjs https://a.com https://b.com --shots 4
Output lands in design/refs/: REFERENCES.md (read it), refs.json, shots/*.png.
Finding candidates.--from awwwards is the only harvester wired in, because it is the only
gallery whose listing and detail pages render reliably headless and expose the outbound site
URL. For everything else — godly.website, curated.design, minimal.gallery, land-book, siteinspire,
thefwa, lapa.ninja, mobbin — use web_search to find the write-ups, then pass the site URLs to
refscout positionally. Searching for the page about a site is more reliable than scraping the
gallery that lists it.
Naming a technique you can see but can't name. originkit.dev is a catalogue of ~160 motion
effects, each with a live preview and a name — useful when a reference does something you want to
describe in the commit-sheet and have no word for. Browse it, take the vocabulary, then build the
thing yourself; the components are React/framer-motion behind a signup, and half the catalogue is
the exact drop-in ornament slopscan exists to keep out.
Reading a fingerprint
Each entry reports what the page actually loaded and did, not what its marketing says:
stack — libraries found in the JS the page really fetched. Bundlers hide globals, so this is
matched against bundle text; treat it as strong evidence, not proof. GSAP + ScrollTrigger + ScrollSmoother + Lenis is the house style of the entire awwwards top tier — seeing it for the
fifth time is the useful signal, not a coincidence.
mechanics — the derived read: pinned scenes (counted from .pin-spacer elements ScrollTrigger
leaves in the DOM), WebGL driven by scroll, sticky stacks, CSS animation-timeline, mix-blend
layers, custom cursor, scrubbed video. This is the column you are actually shopping in.
page shape — 22× viewport tall · 14 sections tells you the scroll budget the reference spends.
A 22× page with 4 pinned scenes is a different film from a 3× page with one WebGL hero, and the
difference is a decision you have to make too.
type / palette — the fonts and colours as painted, sampled from computed styles. LayGrotesk + PPNeueMontrealMono, Thunder + PP Fraktion Mono — this is where you learn that the top tier is not
running Inter, which is exactly ban #8 with receipts. The display face is measured as the largest
painted text (Thunder, sans-serif 118px/800), never the first h1, because a hidden or
fallback-styled heading reports whatever the cascade left there and will cheerfully claim an
awwwards winner ships Inter. The px figure is evidence too: this tier runs display type past 100px.
shots — hero plus scroll stops at 1440. Look at every hero. Look at the remaining stops only
for the 2–3 sites you actually take a steal from. At --limit 8 --shots 3 that is 23 images and
reading all of them is not triage, it is a context bonfire. The numbers tell you the machinery;
your eyes decide whether it is beautiful — but only for the references you are actually using.
⚠ "NO CAPTURE" entries
Some sites hand a headless browser the server-rendered HTML and then never deliver their CSS or JS
(edge-streamed pages, bot walls). Anything read off such a page — fonts, colours, stack — would be
Chrome's defaults dressed up as findings, so refscout reports nothing for them rather than
something false. Roughly 1 in 8 award sites lands here. When it does: open the URL yourself, or
describe it from the gallery write-up, or drop it. Never quote a fingerprint the tool refused to give.
The steal rule
Every entry has a **steal:** line and it is not decoration — fill it in, one line, before you
close the file:
"madewithgsap.com — the section title stays pinned while its cards scroll through it; we do this
once, on the proof scene, with the product name instead of a title."
Rules, in order of how often they are broken:
One idea per reference, named as a mechanic — "pinned title, content scrolls through", not
"cool scroll effect", and never "the vibe".
Adapted, or it is theft. A reference is a starting camera position, not a set. Changing the
colours of a copied layout is not adaptation.
Two references maximum feeding one scene. Three is a collage, and collages read as slop.
Never cite a reference you did not look at. A fingerprint without eyes on the shots is half a
reference.
Named brand assets — logos, custom typefaces, photography, illustration — are theirs. Mechanics
and structure are free; identity is not.
Feeding the commit-sheet
Recon changes what you write in the commit-sheet, especially field 6:
The stacks and mechanics you saw five times ARE the first-order reflex (6a) for this category. If
your peak is the fifth pinned-WebGL-hero of the day, you found the mode, not an idea.
The type and palette columns give you a real, dated map of what the category currently looks like
— much sharper than reasoning about it from memory.
Any mechanic you take goes into the motion budget (field 5) as one of the ≤3 families, not on top
of it.
In the direct register, put the 2–3 references and their one-line steals in the STORYBOARD header
(References taken) so the decision survives into the build.
Output lands in design/moodboard/: contact-sheet*.png (look at these), numbered img/NN.jpg,
and MOODBOARD.md mapping every tile number to its origin page. Twenty tiles arrive as one image,
so reading a moodboard costs one look, not twenty.
Sources (all no-auth, tried in this order and interleaved so none owns the sheet):
bing — the workhorse. Bing's image index reaches into Pinterest, Dribbble and Behance CDNs and
serves originals that hotlink fine through a browser context.
pinterest — logged-out search renders a partial grid behind the login wall: sometimes ~15 pins,
sometimes zero, day to day. Genuinely useful when it answers, never load-bearing; when it returns
nothing the script says so and bing has already covered it.
arena — the public are.na search API. Lower volume, highest curation: these are blocks designers
saved for themselves.
Query craft
The quality of a moodboard is decided entirely by the queries. Three rules:
Two or three queries on different axes, never one. A single query returns near-duplicates of
one template. Pick axes: subject/medium ("ceramic studio photography"), treatment ("hard rim
light, deep shadow"), graphic language ("swiss grid poster, red accent").
Search the feeling, not the category."coffee website" returns other coffee websites — the
category reflex, delivered to your desk. "steel and steam, industrial macro, warm shadow"
returns material you can actually direct from.
Check the anchor noun is not half of a fixed compound."polished brass instrument macro"
returns trumpets and saxophones, because brass instrument is one word to a search index. Same
trap: hard surface, light bulb, glass ceiling, sound board, steel drum. The noun is supposed to
ground the query, and an idiom hijacks it instead.
Anchor a treatment query with a concrete noun. Image search collapses an abstract phrase to
its most commercially indexed substring: "hard rim light on dark glass, wet stone, near-black macro" came back as hard surface — hi-vis workers, gravel, granite pavers. "wet black stone, single hard light" does not. When one query of three drifts, that is the mechanism.
Never search a brand you intend to resemble. That is the shortest path to a page that looks
like a competitor with the logo swapped.
Reading the sheet
Fill the four lines at the bottom of MOODBOARD.md — the moodboard exists to produce these, and an
unfilled index means the sheet was decoration:
dominant palette across the tiles you liked → commit-sheet field 2, converted to OKLCH. Take
the relationship (drenched single hue / near-mono with one accent / earthy midtones), not a
literal eyedropper.
light and contrast character → the lighting: line of every scene-sheet and the literal
lighting parameter in generated-asset prompts (assets.md §1).
one composition move worth stealing → commit-sheet field 4 (grid break).
what to explicitly avoid from these → a real answer, because a sheet always contains the
category reflex too, and naming it is how you stop drifting into it.
Expect 10–20% junk per sheet. It usually is not spread evenly: one query drifts wholesale while the
others stay clean, so read the junk as a signal about that query, not about the sheet. Ignore the
strays; re-run only if a whole axis came back wrong, and re-run that axis with a concrete noun.
Reference images are not assets
Downloaded images are direction only. They are other people's work, they are not licensed to you,
and none of them ships:
never place a downloaded image in the page, not even as a placeholder that "we'll swap later";
never reproduce one composition — the moodboard sets palette, light and energy, and the actual
frames get generated per assets.md;
when the art direction is locked, the moodboard's job is done: it informs the generation prompts
and then stays in design/.
design/moodboard/ and design/refs/ are working artifacts. Ship them to no one and add them to
.gitignore if the repo is public.
When recon fails
symptom
what it means
do this
awwwards listing returned no cards
the gallery markup moved
fall back to web_search + positional URLs
most entries are NO CAPTURE
network or a broad bot wall
profile fewer, better-known sites; lean on the shots and your own eyes
pinterest returned 0
login wall, normal
ignore, bing covered it
the sheet is 20 variants of one image
single narrow query
re-run with 2–3 queries on different axes
one query's tiles are a different subject entirely
search collapsed an abstract phrase to a common substring
re-run that axis anchored to a concrete noun
a script looks hung for minutes
you piped it through tail/head
both stream progress to stderr; drop the pipe to watch it
references all look alike
you found the category mode
that IS the finding — write it into reflex-check 6a and deviate
Recon is bounded. If it has not produced a usable read in one pass, stop and decide from
taste.md — a director who cannot find a reference still has to shoot the film.