Skip to content

Hush

Hush is a site for a horror attraction: a walk-through haunt or scare maze, a horror escape room, immersive theatre, a ghost tour, a dungeon or dark-history cellar, a seasonal Halloween event. It’s made like a walk through a vaulted cellar by torchlight: the whole page, full width, is a brick vault in the dark with a faint film grain, and one warm beam follows the visitor’s pointer (on touch screens it drifts by itself). Walk-throughs are case files with their dread level in small wax seals; on the home page the photo of the way in stays dark except where the torch falls, and each room comes up out of black as you scroll down to the lowest vault. Between pages the lights go out and come back up. The tone is adult and quiet: dread rather than cartoon scares.

Hush 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.

Page Edit it in
Home Pages → Home page (a list of sections)
Walk-throughs, groups, the bar, journal, visit, 404 Pages → the page’s own entry
Walk-throughs (tagline, dread, depth, minimum age, time, group size, price, when it runs, warnings, a photo, tickets) Content → Walk-throughs
Journal posts Content → Journal
Name, description, email, phone, address, navigation, header button, profiles, social picture Pages → Site settings
Buttons, labels, the five dread levels, chat, search, emails, game texts Content → Interface texts
Privacy, terms Pages → Legal

In headlines, words wrapped in *stars* are set in italics in the candle light (oxblood in the light theme), as in “Some doors are left open *on purpose*”.

  • A walk-through has a tagline, a summary, its dread level (1 to 5), its depth, the minimum age, the running time, the group size, the price, when it runs (days and times, as you want them shown), its warnings (darkness, strobe, touch…), a photo (4:5) and a colour. The names of the five levels are in Interface texts → Walk-throughs; what each level means is on the walk-throughs page (the dread scale).
  • Tickets: turn on “Sell tickets with Stripe Checkout” on a walk-through and put a one-time Price id there; its page then has a working button. Buyers come back to /experiences, and the Stripe webhook (/api/stripe/webhook) emails them, where you can add your own steps.
  • Groups and private hire: what groups can book, how it works, and booking a date on Cal.com.
  • The bar: opening hours, the drinks, special nights and a list to join.
  • Visit: opening hours, safety and the safe word, who shouldn’t come, a map, getting here, questions and a contact form.
  • Quotes on the home page: only real quotes with their source. Age limits, warnings and health advice are yours to keep true to your attraction.

The visit page shows the streets round your entrance, drawn in the brand’s colours from OpenStreetMap. Put your entrance’s coordinates in map.config.json (center) and run npm run map; it downloads the area once and writes src/data/location-map.json. A pin marks the entrance with your name, and the card links to directions in Google Maps, Apple Maps and OpenStreetMap.

Everything works without keys; each feature switches on with its variables in .env.example.

Feature Where Service
Tickets Each walk-through’s page Stripe
Groups and private hire Groups page (/groups); a preview of the calendar until it’s connected Cal.com
Newsletter and the special nights list Home, journal and bar pages, with a welcome email Supabase
Contact form Visit page; messages go to the email in Site settings Resend
AI chat On every page, answers from your walk-throughs, the dread scale, groups, the bar, the visit page and journal Claude
Search ⌘K or the search button: walk-throughs, journal, groups, the bar, visit built in, or Algolia
Analytics Every page; Google Analytics only after consent Plausible, Umami, Google Analytics

The home page is built from these sections, in any order: The threshold (with tonight’s doors, and “What the torch finds”: a second version of the photo, same size and framing, shown only inside the torch’s beam; the demo has someone standing in the doorway), The descent (three to five rooms, top to bottom, each with a depth and a tall photo), Walk-throughs, House rules, Feature (a photo and a text, e.g. the bar or private hire), Numbers, Quotes, From the journal, Newsletter sign-up and Closing call.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (oxblood: buttons, the wax seals), the second (the candle: the torch beam, links in the dark, warm fills) and the third (verdigris: cool fills and the faint tint of the dark). Buttons are darkened until their text is readable, the fills are lightened until ink text on them is; a color that can’t get there stops the build with a message. The site opens in the dark theme whatever the visitor’s system is set to; the light theme, limewashed plaster upstairs, comes on with the toggle. Brand also sets the fonts (a tall display serif for headings, the text font and a typed face for labels) and the corners.

Hush is ready for more languages: see Languages.

A small game, Don’t look: a dark room lit only by your torch. Move the light with the mouse, a finger or the arrow keys and take the key (click, tap or Enter). Something stands in the room with you: while the light rests on it, it comes a step closer, and three steps end the game. The battery runs down in every room. Five rooms; the best score is kept in the visitor’s browser.

  • AGENTS.md describes the project for coding assistants (Claude Code reads it through CLAUDE.md, Cursor through .cursor/rules/).
  • /llms.txt lists your pages, walk-throughs and journal for AI assistants, in every language.
  • Pages carry JSON-LD: the attraction as a TouristAttraction, walk-throughs and special nights as Events, groups as a Service, the bar as a BarOrPub, the visit questions as a FAQPage, and each post.
Terminal window
pnpm dev # local site, editor at /keystatic
pnpm build # production build
pnpm map # redraw the map from map.config.json
pnpm 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).