Geodesic. — the build
A single-screen three.js piece about the geodesic ration: twenty flat icosahedron faces subdivided live at frequencies ν1 → ν2 → ν3 → ν5, every new vertex projected onto the sphere, every strut counted honestly — and then the Montreal move, the top hemisphere lifted away as a dome over a tiny lit ground plane.
Concept
Geodesic is a fictional engineering atelier that rations spheres into buildable triangles. The audience is anyone who has stood under a dome and wondered why it holds; the page's single job is to show a sphere being earned — twenty flat triangles becoming a smooth ball before your eyes, then becoming a roof. The strut ledger keeps the arithmetic in view the whole time: struts = 30ν², nodes = 10ν² + 2, and the count of distinct strut lengths measured off the live geometry, never hard-coded.
Palette
Type
Jost (200–600) carries the display voice — its geometric roundness is the right register for a subject that is literally circles rationed into lines; the wide-tracked uppercase wordmark and the giant 200-weight ghost numeral (ν1…ν5) are the typographic bravery. Overpass Mono sets everything that counts: the strut ledger, formulas, captions — an engineer's hand for an engineer's subject. A happy accident kept on purpose: in both faces the Greek ν reads like a lowercase v, so the frequency notation stays legible to civilians.
Techniques
Vanilla three.js (pinned r160 module build), no other libraries. The subdivision is real, not a morph-target trick: for frequency ν each of the 20 icosa faces is gridded into ν² small triangles by barycentric interpolation, vertices are deduplicated across shared edges into a global map, and each vertex keeps two homes — its flat position on the face plane and its projected position normalised onto the sphere. The signature animation lerps every vertex between the two while gold flares mark the newly minted nodes, and the ledger reports edges.size straight off the deduplicated edge set: 30, 120, 270, 750 — exactly 30ν². Distinct strut lengths (1, 2, 3, 9 kinds) are measured by clustering live chord lengths.
The dome phase partitions edges by whether both endpoints sit at or above the equator: the top set lifts on its own group while the bottom hemisphere fades and drops, a shader disc (radial gold-steel glow) and a rim ring fade in beneath, and the camera cranes up so the ground plane opens into an ellipse. Rendering is LineSegments plus Points with procedural canvas dot sprites; fog gives the wireframe depth. rAF pauses on document.hidden, DPR is capped at 2, context loss swaps in a CSS-drawn dome, and reduced motion renders one settled frame — the dome at ν3, mid-morph — with the step control re-rendering static states.
| Frequency | Struts (30ν²) | Nodes (10ν²+2) | Faces (20ν²) | Strut lengths |
|---|---|---|---|---|
| ν1 | 30 | 12 | 20 | 1 kind |
| ν2 | 120 | 42 | 80 | 2 kinds |
| ν3 | 270 | 92 | 180 | 3 kinds |
| ν5 | 750 | 252 | 500 | 9 kinds |
Iteration log
Pass 1 — Craft
Drove the full cycle headless and read the ledger at every phase: counts came back honest (270 struts at ν3, 750 at ν5, 9 chord kinds at ν5 — matching published 5v chord-factor tables). Two real defects found by looking, not loading: the "lit ground plane" was invisible because the camera sat level with it — the disc rendered edge-on as a bare line — fixed by craning the camera up 0.58 units with the lift so the ground opens into an ellipse; and the ladder's law line set ν through text-transform: uppercase, silently turning it into a Latin-looking capital Ν ("STRUTS = 30 N²") — removed the transform. Also swapped three.js's square default points for procedural canvas dot sprites.
Pass 2 — Depth
Made the frequency ladder live: the 1 · 2 · 3 · 5 marks are now buttons that re-ration the form directly (ν5 jumps straight to the dome), with display-value smoothing so a manual jump cranes and fades instead of hard-cutting. Added the second-read detail — every few settled seconds one lone strut glints gold, picked at random from the live top edge set. Ground light now leads the lift (opacity eased by e^0.55) so the ~7s resting frame shows the dome rising over an already-lit plane, and the Biosphère caption arrives 0.4s earlier so it breathes for the full dome hold.
Pass 3 — Hardening
Chanel rule: removed the outer 1.55-radius orbit ring and shrank the glow disc — the concept says a tiny lit ground plane, and the single rim ring reads cleaner. 375px re-verified: scrollWidth exactly 375, wordmark, nav, ledger and colophon all inside the viewport, composition raised so the dome clears the panel. Confirmed zero console errors across the full driven cycle, context-loss fallback wired, rAF pause on hidden tabs, and a clamped-delta clock so tab resume can't skip the choreography.
Driving the ladder end-to-end (not just loading it) caught three more. Jumping from the ν5 dome back to ν1–ν3 left the hemispheres split forever — the lift never lowered; non-dome rations now reset it, so the dome visibly closes on the way down. Stepping into the raise mid-projection lifted a half-flat form; the raise now finishes the sphere before it climbs. And the reduced-motion rest frame kept a stale ghost numeral (a pending 300ms swap timer overwrote the static state) — the swap is now cancelled and immediate under reduced motion. This guide's own counts table also overflowed 375px by 4px; it scrolls in its own container now.
Verification
Headless Chrome (puppeteer-core) against an isolated static server: exactly one h1 per page, zero console errors after a real 7-second settle on desktop and 375px, screenshot-hash liveness 1.3s apart, and a driven pass that steps the entire ration cycle asserting 30ν² struts and 10ν²+2 nodes at every frequency plus a lit ground and honest dome-subset counts in the dome states.