01Client
MERIDIAN
02Timeline
Self-initiated, shipped in slices
03Tech Stack
Next.js, React, TypeScript +3 more
04Live Site
Visit →00In Brief
What
A real-time mechanical-watch configurator for a fictional independent watchmaker: five option axes re-render a procedural 3D watch live, every configuration is a shareable URL, and a cinematic camera with per-preset depth-of-field walks the stage. LAB-03, the second of the Lab’s two WebGL concepts.
What was hard
Configurators usually cheat — swap a texture, call it customisation. MERIDIAN’s bar was state that drives geometry: an open-skeleton dial must reveal a real movement, a chronograph must build real subdials, and selecting any of it must never fan a re-render across the tree or free-run the GPU.
How
Configuration lives in an atomic module-scoped store read through useSyncExternalStore, hydrated from validated URL params and persisted back on change. Materials swap across a PBR registry whose refractive surfaces share one transmission sampler; the watch itself is pure procedural three.js geometry — no imported models. The stage draws on a demand frameloop, and the sonic layer is synthesized in the Web Audio API with no sound files shipped.
Result
Live at /lab/meridian inside the studio site: a drivable instrument in a warm brass register — the thermal opposite of VESPER — with mobile tap-to-focus, reduced-motion poster fallback, and illustrative pricing declared as such inside the panel itself.
01The Challenge
Prove the studio can ship instrument-grade real-time 3D — the inverse skillset of VESPER’s scroll cinema — on a product category where buyers notice wrong details. The watch had to be horologically coherent (complications only where they belong, bracelets without tongue buckles), the interaction had to stay responsive under live material and geometry swaps, and the whole thing had to stay honest: fictional brand, illustrative pricing, declared in the UI.
The Design


02The Approach
An atomic external store is the spine: module-scoped state read through useSyncExternalStore, so one changed axis re-renders only its consumers, with URL hydration making every build shareable. The scene is built from a typed config — dimensions, gear trains, indices — so state changes genuinely rebuild geometry: the open-skeleton dial swaps in a transmissive face over a real movement, and each complication constructs its own 3D detail. Refraction routes through one shared transmission sampler (two independent buffers made the interior “swim”). Around the object: four camera presets with matched depth-of-field, an opt-in cinematic auto-rotate, a synthesized sonic layer, and a mobile focus mode that shrinks the watch to a live thumbnail while the panel takes the screen.
The Solution
01
State Drives Geometry
Choosing open-skeleton renders a real gear train beneath a transmissive dial; date, GMT, chronograph and moonphase each build genuine meshes, gated to combinations that are horologically coherent.
02
Atomic, Shareable State
A module-scoped store read via useSyncExternalStore — no context fan-out, no per-frame setState — hydrated from validated URL params, so a configured watch travels as a plain link.
03
A Stage That Sleeps
Demand frameloop: the canvas draws in response to interaction, camera motion and scroll coupling, then settles back to zero work. The three.js chunk itself hides behind a poster and never reaches reduced-motion clients.
Next case · 01 of 16
Mad Cat Coffee Bar
Specialty coffee / Hospitality · 2026




