Blaze
Blaze is a site for a long-distance trail: trail clubs, hiking guides and trekking outfits, hut-to-hut routes, pilgrim ways, ultra races, anyone who explains one route stage by stage. It is built like a topographic map: real contour lines behind every page, a display serif, and the trail mark (a red stripe between two white ones) as the eyebrow, the bullet and the underline of marked words. On the home page the whole trail is drawn from OpenStreetMap over real terrain relief, with its elevation profile underneath; every stage has a zoomed-in map, its profile and numbers measured from the map. The demo is a fictional field guide, Trailmark, for a real trail: the Heroes’ Trail of the SNP across Slovakia (Cesta hrdinov SNP), from Devín Castle to the Dukla Pass, in English and Slovak.
Blaze comes in two variants, chosen when you create the site: files/Sanity (static pages, any host)
and EmDash (--cms emdash, rendered on request on Cloudflare). The pages are the
same in both.
Pages and their content
Section titled “Pages and their content”| Page | Edit it in |
|---|---|
| Home | Pages → Home page (a list of sections) |
| Stages, guides, journal, 404 | Pages → the page’s own entry |
| Guided trips (the trips, how a week goes, booking, passport and deposits, questions) | Pages → Trips page |
| Plan (the months, trail marks, details, packing list, contact form, questions) | Pages → Plan page |
| Stages (from, to, kilometres, range, difficulty, on the way, water, where to sleep, description) | Content → Stages |
| Guides (role, home ground, qualifications, languages, biography, portrait) | Content → Guides |
| Journal posts | Content → Journal |
| Name, the trail’s name, contact, navigation, header button, profiles | Pages → Site settings |
| Buttons, labels, map texts, chat, emails, game texts | Content → Interface texts |
| Privacy, terms, safety | Pages → Legal |
In headlines, words wrapped in *stars* are underlined with the trail mark, as in
“From Devín to *Dukla*”. A line break in the home page’s headline starts a new line.
The trail map
Section titled “The trail map”The map is drawn once, on your computer, by pnpm map, from what map.config.json names:
trail.relation: the trail’s OpenStreetMap route relation. Find the trail on openstreetmap.org, open the route and copy its relation number.trail.start: a point near the start, so the line runs the right way.area.relation: a border to draw round it (a country or a region, also a relation), orarea.bbox(west,east,south,north) for a plain rectangle.terrain: the zoom of the relief, how much it exaggerates the hills, how soft it is.
pnpm map -- fetch downloads the trail, the border and open terrain tiles (SRTM, EU-DEM and others)
into .map-cache/, chains the trail’s pieces into one line, measures it, and writes
src/data/trail.json (the trail, the outline, a point per kilometre with its height, the elevation
profile) and the relief in public/map/: two masks the site paints in your colors (so the night and
day maps and every accent use the same files), coarse tiles for the whole area, sharp tiles along the
trail for the stage maps, and the contour lines behind the pages. -- terrain downloads only the
terrain again, -- build and -- render redo the steps without downloading. The maps credit
OpenStreetMap and the terrain data; keep the credits.
On the home page the trail draws itself, the relief fades in after the page has loaded and the map tilts a little with the mouse. Point at the trail or the profile and a hiker goes to that kilometre, with its height and stage; a click or tap pins it with a link to the stage, and the arrow keys walk it (Shift for 10 km). On phones the map is wider than the screen and scrolls sideways. The names of ranges and places on the map are content (Home → The map → Names on the map), placed by coordinates.
Stages
Section titled “Stages”A stage has a number, where it starts and ends (names, and kilometres from the start of the trail: point at the trail on the home page to read them), its range, a difficulty, a summary, what is on the way, water and where to sleep, and a description. Distance, climbing, descent, the highest point and the walking time are measured from the map between the two kilometres, so they always match it; the walking time uses the standard hiking formula (4 km an hour, 300 m up and 500 m down an hour). Stages are listed by range on the stages page, each card with its profile; a stage’s page shows it zoomed in on the relief, the rest of the trail faint, with its profile and the previous and next stages.
Guided trips, booking and payments
Section titled “Guided trips, booking and payments”The trips page holds up to four trips, each with its stretch of the trail (fromKm, toKm) drawn on
its card (mark one as the favourite), how a guided week goes, booking a planning call with Cal.com and
what you sell with Stripe (the demo: a trail passport, a map set and a deposit), each with a one-time
Price id. Without keys, the booking shows a preview of the calendar and the payment buttons explain how
to switch them on.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Book a planning call | Trips page, loads on click; a preview of the calendar until connected | Cal.com |
| Passport, maps, deposits | Trips page (one-time Price ids) | Stripe |
| Newsletter | Home and journal pages, with a welcome email | Supabase |
| Contact form | Plan page; messages go to the email in Site settings | Resend |
| AI chat | On every page, answers about the stages (with their numbers), planning, trips and guides; never promises that a section is safe or open | Claude |
| Search | ⌘K or the search button: stages, guides, journal, trips, plan, in the page’s language | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics |
Sections
Section titled “Sections”The home page is built from these sections, in any order: The map (the opening), The story (why the trail has its name: a few paragraphs beside a timeline), The climb (the whole profile, walked by a hiker as you scroll, with marked places), Stages (cards with their profiles), Trail marks (big words between trail marks, sliding as you scroll), Three steps (along a dashed trail), The guides, Numbers, Journal, Newsletter and Closing call (a wide photo whose top edge is cut along the trail’s real profile). With reduced motion the trail stands drawn, the profile complete and nothing moves.
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent
(the trail mark: buttons, the trail on every map, marks), the second (the forest: the night map,
the land and the panels take its hue) and the third (dawn: the hiker, summits, the current tab).
Buttons are darkened until their white text is readable and every pair is checked; a color that can’t
get there stops the build with a message. Brand also sets the fonts (headings and text, all with
Central European letters) and the corners. The night map is the default; the paper map comes on when
the visitor’s system prefers light, or with the toggle, and the browser remembers the choice.
Languages
Section titled “Languages”Blaze ships in English and Slovak, with a switcher in the header and the menu; Slovak pages live
under /sk/. Add or remove languages as described in Languages.
The 404 page
Section titled “The 404 page”A small game, Follow the blaze: at every fork in a foggy forest a trail mark shows on one of three trees for a moment; take that path (left, straight on or right: the buttons, the arrow keys or a swipe) before the fog closes in. Later forks add green and yellow marks of other trails to throw you off: only the red one is yours. Every fork adds to the kilometres walked; the best walk is kept in the visitor’s browser.
AI assistants and search engines
Section titled “AI assistants and search engines”AGENTS.mddescribes the project for coding assistants (Claude Code reads it throughCLAUDE.md, Cursor through.cursor/rules/)./llms.txtlists your pages, stages (with their numbers), guides and journal, in every language.- Pages carry JSON-LD: an
Organization, stages and trips asTouristTrips, the guides asPersons, questions as aFAQPage, and each journal post as aBlogPosting.
Commands
Section titled “Commands”pnpm dev # local site, editor at /keystaticpnpm build # production buildpnpm map -- fetch # draw the trail map from OpenStreetMap and terrain datapnpm cms sanity schema|seed # move content to Sanity (see Content → Sanity)In the EmDash variant: npm run dev, npm run deploy (Cloudflare) and npm run emdash:schema
(after changing the content model).