CONTOUR is one of 25 sites designed and built by Formwork to show web design, motion, and restraint. The hero is a living topographic map — real iso-contours computed live from a drifting noise field. Here is exactly how it was made.
The brief was cartographic: an expedition brand whose homepage feels like reading a map before a walk. Rather than a photo of a mountain, the mountain is generated and contoured on the fly — nested elevation rings that drift, breathe, and label their own altitude. Everything else — condensed Oswald headings, a Spectral serif for route names, mono for coordinates — is set on warm paper to frame that one moving surface.
main branch.Each frame samples a scalar field onto a grid. For every cell — a square of four grid points — the four corners are tested against an iso-value. That gives a 4-bit case (0–15), and each case says which cell edges the contour crosses. Linearly interpolating the crossing point along each edge yields the line segment. Do that for ~17 iso-values and you have a topographic map; make every fourth one thicker and it reads as index contours.
// four corners → 4-bit case → interpolated crossings
let idx = 0;
if (tl > L) idx |= 8; if (tr > L) idx |= 4;
if (br > L) idx |= 2; if (bl > L) idx |= 1;
const ax = x0 + sx*(L-tl)/(tr-tl); // top edge X
const dy = y0 + sy*(L-tl)/(bl-tl); // left edge Y
switch (idx) {
case 7: case 8: seg(ax, ay, dx, dy); break; // one corner cut
case 3: case 12: seg(dx, dy, bx, by); break; // left→right
// …14 cases, two saddles
}
The field itself is 3D value noise: sampling a slowly advancing z makes the
terrain morph smoothly instead of teleporting, while a few Gaussian "peaks" with drifting centres
guarantee the iconic nested rings. A tiny sine offset on every iso-value makes the whole map
breathe. Labels are placed greedily along index contours and drawn with a paper-coloured
halo — which is exactly how a paper map leaves a gap in the line for its numbers.
.loaded class with a 400ms failsafe, so a stalled CDN can't leave it empty.Every site here is static, so hosting is three commands:
git init -b main && git add -A && git commit -m "ship"
gh repo create formwork-contour --public --source=. --push
gh api --method POST /repos/OWNER/formwork-contour/pages \
-f 'source[branch]=main' -f 'source[path]=/'
Use relative paths (./main.js, not /main.js) because project Pages
live under /repo-name/. Add an empty .nojekyll file so every asset serves verbatim.
That's the whole recipe: one contour engine, a little motion, strong type, and static hosting. The other 24 sites each swap the central technique — shaders, particles, kinetic type — but the discipline is the same.