20 · Hollowback 50K: a trail race you fly through on a real mountain

Hollowback 50K is a race website for a made-up 31 mile trail race on the real terrain of Mount Greylock, Massachusetts. The race, its stations, cutoffs, prices and waves are fictional, and the footer says so. The mountain, the trails and the towns are real. What makes people stop: one 3D terrain map sits behind the whole top of the page, and as you scroll the red course line fills in, the camera follows a runner dot along it, and an elevation strip at the bottom lets you drag the runner anywhere on the course.

Inspiration

This is the batch three approach: a tested kit plus a theme, with the page itself written by hand. The map comes from the lab tools MapLibre and OpenFreeMap, wrapped by the kit part maplibre-file.js (terrain, a growing route line, and a restyle function that recolors the street map to the brand). The hand-drawn accents in the aid section are four Kitbitz drawings (Tent, Backpack, Lantern, Bonfire). GSAP with SplitText, ScrollTrigger and DrawSVG does the intro, card reveals, bib animation and the drawing-in of the art. The glass legend uses the kit's SVG-filter glass.

Added on top, written for this page: contour lines computed in the browser from a terrain grid with marching squares (OpenFreeMap has no contours), a camera that blends from a slow hero orbit into a route-following camera, a pace calculator that sets arrival times against cutoffs, and a bib generator that exports a PNG.

Visual direction

Theme, kit and licenses

Theme: Map, at the Loud end of its budget. Runners and entrants need to see the course and its climbs first, so the map is the whole show and every other element serves it. One line of the theme recipe changed: contours are drawn from the builder's own terrain grid because the tile source has none.

Kit parts used: maplibre-file.js (map, terrain, route, restyle), kitbitz.js (the four drawings, recolored to the palette), glass.js and glass.css (one legend panel, not sticky), fps-chip.js (the ?fps readout). No new libraries.

Source License
MapLibre GL JS 6.15.0 BSD-3-Clause
OpenFreeMap tiles and "liberty" style Free, attribution required (shown)
OpenStreetMap data ODbL, attribution shown
Mapzen terrain tiles on AWS Open data, credited in the map attribution
FOSSGIS foot router (OSRM) Public service on OSM data; used once while building, nothing called at runtime
Kitbitz drawings CC0, credited anyway
GSAP 3.15.0 and plugins GSAP standard no-charge license
Big Shoulders Display, Inter Tight SIL Open Font License
Glass, map and chip kit parts Our own code

References

Why these choices

A race site has two jobs: show what the course is like, and get people to enter. The terrain map does the first better than any photo, and the pace check and entry form do the second. The pace check is the practical hook: it answers "can I make the cutoffs?", which is the real question every entrant has.

Trade-offs worth knowing. The live map depends on a free tile service with no uptime promise, so a drawn topo map (same contours, route, aid markers and runner dot) shows first and takes over if WebGL or tiles fail. Glass is used once, in the hero, because it costs frames over moving content; the HUD and profile are solid for the same reason. With reduced motion the page does not fly: the camera shows the whole course and scrolling still reads progress. The cards sit left so the runner stays clear of text, and on phones the camera padding moves the runner above the cards.

Who this kind of site is for

It wins for trail and road races, cycling events, guided tour companies, ski areas, hiking guides and anything sold by "where it goes". It is wrong for businesses with no route or place to show, and for pages that must load fast on weak phones, since it pulls a map library and terrain tiles. To pitch it: "Your course, as a flyover, with a calculator that sells the race." A real client would swap the traced line for their own GPX file and keep everything else. The pace-and-wave logic reuses for any timed event with checkpoints.

How to make it

Stack and key techniques

The prompt

Build a single-file website (index.html, no build step) for a FICTIONAL 31 mile trail race, "The Hollowback 50K", run on the REAL terrain of Mount Greylock, Massachusetts. Say plainly in the footer that the race, stations, cutoffs, prices and waves are made up and the mountain is real.

Theme: "Map, Loud". The map is the whole show. Palette: dusk #141a26, topo tan #c8b48a, trail red #e5484d, snow #f4f1ea. Fonts: Big Shoulders Display (headlines, big numbers) and Inter Tight (body).

Structure: (1) A hero over one sticky full-screen 3D map (MapLibre with OpenFreeMap, restyled dark, terrain and hillshade) that orbits slowly. Include one glass stats panel: 30.7 miles, 7,800 ft, 6 aid stations, 14 hour limit. (2) A fly-through: seven solid (never blurred) chapter cards, one per section of the course. As the user scrolls, the camera drops in and follows a runner dot along the route; the red route fills as they go, mile markers appear as they pass, aid stations light up. A solid HUD shows mile, feet and trail name. A sticky elevation profile at the bottom shows the runner; hover, drag or arrow keys move the runner and fly the camera. Add a camera toggle (follow / overview). (3) An aid-station section on snow-colored paper with faint contour lines behind it: a table of six stations plus finish with cutoffs, and a pace check (goal-time slider, start wave chips) that marks each arrival OK, tight or missed, with a timeline graphic. (4) An entry form with real validation that shows a tilted race bib with a generated number and lets the user save it as a 1400x980 PNG.

Data: trace the course once along real OSM foot paths, measure it against open terrain tiles, and store the line, elevation profile and a coarse terrain grid in an inline JSON block. Draw contour lines in the browser from that grid (marching squares) and add them to the map, because OpenFreeMap has none.

Motion: GSAP with SplitText, ScrollTrigger and DrawSVG; split-character title intro; Kitbitz (CC0) drawings in the aid section, recolored to the palette and drawn in.

Rules: show a drawn SVG topo map first and as a full fallback if WebGL or tiles fail, with the same moving runner. Honor prefers-reduced-motion (no orbit, show the whole course). No blur on sticky elements. Keyboard operable, visible focus, no horizontal scroll at 390 or 1440 px. No em dashes. Credit all sources with licenses.

Verify: screenshot at several scroll stops on desktop and mobile, with and without reduced motion; click through the pace check and the form; test the fallback with the map disabled; check the console; fix and repeat.

Build notes

Stepping down: what you would likely lose

This is an informed estimate, not a measurement. No public benchmark compares these models on one-shot frontend work, and the kit helps more than model tier does here.

Feature Sonnet 5.5 with this kit Sonnet 5.5 from a blank page
Live 3D map, terrain, restyle Does fine: the kit part already handles the file-open worker problem and styling Attempts it with likely bugs: a blank map from a double-clicked file, or a muddy default style
Route fill and mile markers Does fine: the kit's route helper has a progress setter Likely bugs in line gradients or progress animation; may swap in a plain line
Contours from the terrain grid Attempts it with likely bugs: stitched lines with gaps or jagged edges (the joining step is the hard part). Data prep is separate work Probably simplifies away, or uses a flat background image
Follow camera blending from the orbit Attempts it with likely bugs: jitter, a spin the long way round when bearing wraps at 360, and the runner hiding behind cards Probably a simple jump to a fixed zoom
Draggable profile with keyboard and readout Does fine in the main case; touch capture and blur cleanup are the weak spots Attempts it with likely bugs: a mouse-only drag
Pace check and bib PNG Does fine: this is ordinary logic, though the second-half slowdown model may be simpler Does fine, probably with a plainer effort model
Drawn fallback map Attempts it with likely bugs: contours not matching the live map Probably simplifies away

Rough overall estimate, a judgment call: with the kit and the same prompt, perhaps 70 to 85 percent of the visual impact in one pass; from a blank page, perhaps 40 to 60 percent, mostly lost in the map camera and contours. What would close the gap: a screenshot loop at several scroll stops, and splitting the build so the course data and contour code are done and checked before the page is assembled.

← Previous reportNext report →