- Shipped
- August 19, 2026 at 2:22 AM UTC
- Author
- Kamo
- Commit
- 79d2ffe
The hero pointed a bare <video src> at a single 3.9 Mbps 720p24 MP4, so a phone on a weak connection downloaded exactly the same stream as a desktop on fibre, and kept downloading after the visitor scrolled past. It now plays the 720p/540p/360p ladder built by KlusterServices' hero-hls-encode job: the player takes the rung its connection carries and fetches ~4s segments only while watching. The 360p rung is 5.4 MB against the original 31.8 MB. Playback moves out of the JSX and into an effect because choosing between HLS and the MP4 is a runtime decision. Safari and iOS get the playlist natively (iOS has no Media Source Extensions, so hls.js is not an option there); everyone else gets it through a dynamically imported hls.js that stays out of the entry bundle. A fatal hls.js error, an unsupported browser, or a failed chunk load all land on the original MP4, which is still the source of truth. The <video> deliberately carries no `src` — declaring one would start the 31.8 MB progressive download this change exists to remove. hls.js becomes a direct dependency. It was only present transitively via @react-three/drei, which is no longer in package.json at all; npm install pruned its 67 leftover packages from the stale lockfile. Nothing in app/ imports drei, three, or react-world-flags (FlagEmoji.tsx documents replacing the last of those on purpose). The poster attribute also starts working: it has referenced public/kamo12-poster.jpg since this component was written, but the object never existed and the hero rendered blank until the first frame decoded. The encode job now publishes it.