03substrate
COLOPHONhow this site is built
This site is the third exhibit. Here is how it is engineered, what it costs, and what was deliberately left out.
01Measured
Measured
Figures from the Phase 3 production build.
- initial js
- 189.4KB gz
- budget
- 200KB gz
- webgl chunk
- 268.9KB gz, lazy
- css
- 9.3KB gz
- fonts preloaded
- 127.5KB, 2 files
- contrast floor
- 4.66:1
- runtime dependencies
- 6
02Architecture
Architecture
Next.js App Router with TypeScript in strict mode, plusnoUncheckedIndexedAccess. All content lives in typed records under src/data, and the route table is a single source of truth that drives navigation, titles, metadata and route announcements alike.
Styling is a four-tier token system: raw values, semantic aliases, per-level overrides, then component recipes. A component never names a raw value. That boundary is load-bearing — the one time it was crossed, light-mode text ended up rendering at 1.07:1 against its own background.
Roughly 85% of motion is CSS. The WebGL scene is lazy and demand-driven, so it is never in the initial bundle and the renderer is idle unless something asks it for a frame.
03Rejected
Rejected
The more useful half of a dependency list is the part that is not in it.
Framer Motion
44 KB gz
The site asks for a fade, a translate and a stagger. That is thirty lines of IntersectionObserver and a CSS transition.
GSAP + ScrollTrigger
27 KB gz
Its pin injects a spacer and rewrites layout. `position: sticky` pins natively; what remains is arithmetic on a bounding rect.
anime.js
21.5 KB gz
Carried for one two-element stagger. Removed in Phase 2; the native Web Animations API does the same work for nothing.
Smooth-scroll libraries
5.3 KB gz
Decoupling scroll from the OS scroller reads as lag on a low-power machine at any easing.
Post-processing (bloom, chromatic aberration)
~50 KB gz, and fill-rate bound
The performance shape was set on a 2015 dual-core with integrated graphics. Full-screen bloom would undo that, and cost battery on mobile.
A component, icon or state-management library
varies
Nothing in this site needs one. Every dependency is a maintenance cost that outlives the reason it was added.
04Verified automatically
Verified automatically
Continuous integration fails the build on any of: a type error, a lint error, a failing unit or content-integrity test, a bundle over budget, an accessibility violation at desktop or mobile width, or a dependency advisory at high severity.
Two of those are unusual and both exist for the same reason. The contrast suite parses the stylesheet and checks every ink against every surface, so a token cannot be added unverified. The evidence suite fetches every cited source and compares quoted code against the real file line by line — on a site whose premise is that claims are checkable, a dead source link is a correctness bug rather than a content nit.
05Accessibility
Accessibility
Motion is a setting rather than a gate: the operating-system preference is the default and is always honoured, but a visitor can override it in either direction, because plenty of machines report a reduced-motion preference for performance reasons rather than vestibular ones. Under reduced motion the site renders its resting state — nothing hidden behind a transition that will not run. De-emphasis is always a colour token and never an opacity, because the lowest ink on this palette needs 93% alpha to stay above 4.5:1, which makes any perceptible fade an accessibility failure.