Junction
Junction is a site for journeys along a route: a scenic or heritage railway, a tour operator, a tourist region or trail, a boat or bus tour, a festival or conference with a programme. It’s made like a model railway: a panorama the train crosses as you scroll, the stations down a track with a little train riding past them, journeys sold as tickets, a departure board and a visit page with the line on a map. It runs from edge to edge of the window.
Junction 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) |
| Journeys, timetable, journal, visit, 404 | Pages → the page’s own entry |
| Journeys (what you sell, with the route) | Content → Journeys |
| Timetable (days and departures) | Content → Timetable |
| Journal posts | Content → Journal |
| Name, description, email, address, the line (name, length, since), navigation, header button, profiles | Pages → Site settings |
| Buttons, labels, the departure board, chat, search, emails, game texts | Content → Interface texts |
| Privacy, terms | Pages → Legal |
In headlines, words wrapped in *stars* get a brass lining, as in “All aboard for the *valley*”.
The departure and the line
Section titled “The departure and the line”The home page opens with the departure: a wide panorama (about 7:3) that holds still while you scroll through it, while the train runs along the track from the platform and out at the right; its wheels turn and smoke drifts back. The next departures from the timetable show on a board beside the headline.
The line lists your stations in order (two to seven), each with its nameboard, distance, a title, a few lines and a photo; a small train rides down the track in the middle of the screen as they pass, and each station’s signal drops to clear. Both are CSS only; visitors who prefer reduced motion see the train waiting at the platform.
The train, track, signals and nameboards are drawn by the template in your brand’s colours, so they follow every palette.
Journeys and tickets
Section titled “Journeys and tickets”Journeys marked Featured come first, then by Order. Each has a tagline, summary, duration, fare (“£24”) and what it’s for (“adult return”), when it runs, the route (stops with times and an optional note, drawn down a track on its page), what’s included, a photo and a colour.
To sell tickets online, turn on Tickets → Sell tickets with Stripe Checkout and add a
one-time Stripe Price id: the journey’s page shows a button that takes the payment with Stripe
Checkout and brings the customer back to the journey. Until your Stripe key and the Price id are
set, the page says what’s missing. After paying, the Stripe webhook (/api/stripe/webhook) emails
the customer; add your own steps there, such as your seat plan.
The timetable
Section titled “The timetable”Each running day is an entry: a label (“Saturday 18 October”), a date that sorts the days, an optional special day (“Steam Gala”) and note, and its departures (time, journey, station, platform, and a status: on time, few seats, full or special). The home page shows the first days on a departure board, the timetable page all of them. Remove days that have passed, or mark them as drafts.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Tickets | Journey pages with tickets turned on | Stripe |
| Groups and private hire | Visit page, loads on click | Cal.com |
| Contact form | Visit page; messages go to the email in Site settings | Resend |
| Newsletter | Home and journal pages, with a welcome email | Supabase |
| AI chat | On every page, answers from your journeys, timetable, visit page and journal | Claude |
| Search | ⌘K or the search button: journeys, timetable, journal, visit | 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 departure, The line, Journeys, Timetable (the next days), Numbers, Latest from the journal, Newsletter sign-up and Closing call (a photo from edge to edge).
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the
accent is the livery (buttons, the train, the track, nameboards), the second the brass
lining (tickets, highlights, the departure board), the third the painted sky (soft fills, the
train’s windows). Buttons are darkened until their cream text is readable, the second and third
are lightened until ink text on them is; a color that can’t get there stops the build with a
message. The cream baseboard and the night run (deep blue, for the dark theme and the departure
board) are derived from them. Brand also sets the fonts (text, headings, and the mono font for
times and boards) and the corners (rounded like enamel signs, or square).
Languages
Section titled “Languages”Junction is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Switch the points: trains in your brand’s colours leave the yard one by one; tap a junction (or press 1, 2 or 3) to throw its points so each train reaches the platform of its own colour. Three wrong platforms and the signal box closes; the best score 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/), including what makes the look./llms.txtlists your pages, journeys and journal for AI assistants, in every language.- Pages carry JSON-LD: the line as a
TouristAttraction, each journey as aTouristTripwith its stops and fare, the questions on the visit page, and each post.
Commands
Section titled “Commands”pnpm dev # local site, editor at /keystaticpnpm build # production buildpnpm 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).