Skip to content

Build log · Origin Run

Brief

A cinematic chapter — the second of the anthology — rendered as the launch page for a fictional trail-running shoe called Origin Run. The aesthetic target was cinematic in the literal sense: scenes that stack and hold attention, a video texture behind the opening, line work that draws itself as you move through the page, and reveal cadences tuned for pacing rather than punch. The reviewer should hit the cinematic card on the landing page, watch a polygon wipe open the new canvas, and feel the chapter settle into its own speed.

Patterns used

Type and palette

Cormorant Garamond (a high-contrast display serif) for headings, Inter for body and metadata. Cormorant has the thick-to-thin stroke modulation that reads "cinema" on a poster; Inter is neutral enough to stay out of the way for specs and captions. Palette comes from the chapter wrapper:

[data-chapter="cinematic"] {
  --color-bg: #0a0a0a;    // near-black
  --color-fg: #f4f1ec;    // warm paper
  --color-muted: #8a8680; // low-contrast label text
  --color-accent: #d4b472; // brass metadata
}

The chapter is the only dark-theme surface in the anthology. The brass accent is used for scene numbers, the trail path, and the subscribe CTA on future iterations — sparing, never decorative.

Decisions

Four scenes, not five

I drafted five scenes (adding a "why we build in Kentish Town" location scene between manifesto and specs). Cut before shipping. Five stacked sticky scenes puts ~500vh of scroll on the chapter, which exceeds an attention budget I could defend. Four scenes is exactly enough to carry a narrative — hook, argument, object, proof — without feeling like a film-festival edit.

The hero uses LazyVideoBackground, not an always-autoplay <video>

A trail shoe hero could justify a looping 1080p video indefinitely, but the cost is real: ~3–5 MB over the wire, pause/play state to manage on tab switch, autoplay rejection fallbacks. Our component uses IntersectionObserver to attach the media source only when the scene is in view, pauses when it scrolls out, and falls back to an Image poster if autoplay is rejected. preload="none" on the <video> is load-bearing: without it, the browser starts buffering even before the src attribute is set. Safari specifically needs playsInline to keep the video from escaping to fullscreen on iOS; we have it.

overflow: clip, not overflow: hidden

Every stacked scene uses overflow: clip. hidden creates a new scroll container, which silently breaks position: sticky on ancestors and, much worse, breaks the outer Lenis smooth-scroll integration without throwing an error. clip clips the paint without introducing the scroll container. This is the single most common gotcha when building this layout and it is worth writing down every time.

Spec grid reveals with a spring, timeline with slide-up

Both use the same StaggerReveal primitive, but with different animations. Specs pop from 95% scale with an overshoot easing (cubic-bezier(0, 0, 0.11, 2.02)) — the numbers arrive confidently. The timeline entries slide up with the same spring — the dates feel like they're being uncovered, not announced. Same primitive, two personalities, chosen per scene.

The SVG path is scroll-linked, not load-triggered

DrawPath defaults to scroll-linking the stroke-dashoffset to the element's position in the viewport. On entry it draws in as you approach; on exit it retracts (if you reverse scroll). I considered trigger="viewport" — draw once and be done — but the reversibility adds a quiet feedback signal that the chapter is responding to your movement. The performance cost is a single passive scroll listener per path; nearly free.

Per-transition opt-in on the landing page

The landing page's cinematic card carries data-transition="clippath-polygon". The provider registered at the root layout reads the value, picks the polygon keyframes (an 8-point polygon starting collapsed at centre, expanding to cover the viewport), and runs the animation before calling router.push. The provider ignores every other link — the editorial chapter has its own mosaic transition, and ordinary nav links navigate instantly.

Tradeoffs rejected

Performance notes

What I'd change in production

  1. Add a short ambient audio track (muted by default, unmuteable via a corner button) on the hero scene. Trail shoes sell on atmosphere and the site currently does not make a sound.
  2. Pre-render the trail SVG with commissioned illustration rather than a single cubic curve. A detailed trail map with elevation markers and waypoint labels earns its scene.
  3. Lift the ScrollStack to pin Scene 4's CTA for an extra 50% viewport after the last scene lands. Right now the CTA appears and immediately releases; a pin extension would let readers sit with the decision.
  4. Swap the Pexels footage for shot-for-purpose dusk footage. Every launch campaign does; the stock video is a placeholder, not an aesthetic choice.