KINETIC — BUILD GUIDE
KINETIC is a fictional performance running-shoe brand invented for this showcase. One flagship shoe — the KN-1 — presented as a premium deconstructed-product motion site: a full-screen background video is scrubbed frame-by-frame by scroll, while content sections ride over it. Dark graphite base, one volt-green accent, condensed italic display type, mono spec-sheet details.
The signature effect has three parts working together:
<video> driven by scroll. The video never plays.
It sits fixed and full-screen behind the page (muted, playsInline,
preload="auto"), and a GSAP ScrollTrigger with scrub: true
maps scroll progress to the playhead: video.currentTime = progress × duration.
Scrolling forward plays the shot; scrolling back reverses it.ScrollTrigger.update on every scroll event so both systems share one clock.const lenis = new Lenis({ smoothWheel: true })
lenis.on('scroll', ScrollTrigger.update)
gsap.ticker.add((t) => lenis.raf(t * 1000))
gsap.ticker.lagSmoothing(0)
bgv.pause() // time comes from scroll, never playback
ScrollTrigger.create({
trigger: '#scroll-track',
start: 'top top',
end: 'bottom bottom',
scrub: true,
onUpdate: (self) => {
if (bgv.duration) bgv.currentTime = self.progress * bgv.duration
},
})
The scrub track wraps the hero, the pinned deconstruction section, and the tech section — so the video's assembled-shoe first half lands under the hero, and its exploded-stack second half plays out exactly while the deconstruction section is pinned. Sections after the track keep the video parked on its final frame.
-g 1 mattersSetting currentTime is a seek, and video seeks snap to keyframes. A normal
H.264 export has a keyframe every 1–2 seconds with predicted frames between, so scrubbing snaps
between a handful of anchor frames — choppy forward, worse backward. The fix is to re-encode so
every frame is a keyframe, making every seek frame-accurate in both directions:
ffmpeg -i kinetic-scroll-background-raw.mp4 \ -an -c:v libx264 -crf 18 -pix_fmt yuv420p \ -g 1 -keyint_min 1 -sc_threshold 0 \ website/public/bg.mp4
-g 1 -keyint_min 1 — GOP size 1: a keyframe on every frame.-sc_threshold 0 — no scene-cut detection inserting its own GOP structure.-an — drop audio; a scrubbed background is always muted anyway.-crf toward 22–24
before dropping resolution if size becomes a problem.On mobile (≤820px) and for users with reduced-motion enabled the video is not loaded at all — the site swaps in the static hero still as a fixed background and keeps the identical layout.
All media was generated through the Higgsfield MCP. The order is the trick: hero still first, then every other asset uses the hero as its visual reference so the shoe stays the same product across the exploded view, the macro, four colorways, and the video. The video (Seedance 2.0, 16:9, 720p, 10 s) uses the hero as its start frame and is prompted as one continuous shot — a scrubbed background cannot contain cuts, because dragging the playhead across a cut looks broken.
| Asset | Model | Reference |
|---|---|---|
| Hero still | Nano Banana Pro (16:9) | — (the anchor) |
| Exploded view | Nano Banana Pro | hero |
| Material macro | Nano Banana Pro | hero |
| 4 colorways | Nano Banana Pro | hero |
| Scroll video | Seedance 2.0 (720p, 10 s) | hero as start frame |
Every asset came from a carefully art-directed brief — lighting, lens, palette, composition and motion behaviour specified per shot (and, for the video, a strict one-continuous-shot, scrub-stable camera plan) — iterated until the product stayed identical across every frame and matched the volt-on-graphite brand. The full prompt library is proprietary — available to clients on request.
base: './' so dist/ is fully relocatable.The dist/ folder is a self-contained static site — no server code, no environment
variables. Two easy paths:
# drag-and-drop: run the build, then drop dist/ onto https://app.netlify.com/drop npm run build # or with the Netlify CLI npm i -g netlify-cli netlify deploy --dir=dist --prod
If you connect the repo instead, set build command npm run build
and publish directory dist (base directory website).
This guide ships at /guide/ automatically because it lives in
public/guide/index.html.