Haven
Haven is a site for a boutique hotel: small hotels, guesthouses, B&Bs, country inns and small resorts. It is set by the sea at night: deep ink blue with the faint depth contours of an old sea chart, sea glass, candle gold and rose clay, an elegant serif, brass key fobs and a glass pill nav. The home page opens on one room, photographed from the same spot through a whole day as you scroll, with the rating, the headline, one line, Check availability and Call over it from the first frame. The demo is a fictional hotel, Marram House.
Haven 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) |
| Rooms (every room as a card, what comes with every stay, questions) | Pages → Rooms page |
| A room (a page each: size, beds, sleeps, view, features, what’s in the room, from price a night, two photos, availability, questions) | Content → Rooms |
| Book (the booking request, availability, the deposit, policies, questions) | Pages → Book page |
| Dining (the story, menus with prices, the bar, a table, allergies) | Pages → Dining page |
| Spa and experiences (each with how long, price and when) | Pages → Spa and experiences page |
| Offers and packages | Pages → Offers page |
| Gift vouchers | Pages → Gift vouchers page |
| Weddings and events (spaces, what’s included, the enquiry form) | Pages → Weddings and events page |
| Journal | Content → Journal (one page can be for returning guests only) |
| Visit (the map, getting here, hours, arriving, message form) | Pages → Visit page |
| Questions (in groups) | Pages → FAQ page |
| Name, phone, address, check-in, rating, hours, navigation, more pages, profiles | Pages → Site settings |
| Buttons, labels, chat, emails, game texts | Content → Interface texts |
| Privacy, terms, booking and cancellation | Pages → Legal |
In headlines, words wrapped in *stars* are set in italic over a tide line, a thin wave in your accent,
as in “Wake up to the *sea*”.
The hero
Section titled “The hero”The hero is the site’s signature. Four photos of the same room from exactly the same spot (Pages → Home page → Hero → Photos) are revealed one after another as you scroll while the screen stays put:
- Dawn: the linen curtains drawn, glowing pink before the sun is up. It is there from the first frame and is the page’s largest image, so it loads first.
- Morning: the curtains part from the middle behind two seams of sunlight; breakfast on the bed, dust drifting in the beams.
- Golden hour: the evening spreads out from where the sun sits over the sea, the water glittering.
- Night: the sky darkens from the top down, then the lamps come on one by one and the stars come out.
A clock in the caption card counts the hours and minutes from one moment to the next, with the temperature and the state of the sea (“06:12 · 11 °C · Sea calm” to “22:15 · 14 °C · Stars out”); write your own in the hero’s four moments. The later photos load after the page has loaded, so they never slow it down. With reduced motion, or in a browser without scroll-driven animations, the hero is one still: the room at night, with the four moments listed under it.
To use your own room, take four photos from a tripod (the window in the middle), or generate one and edit
it into the other three so nothing moves. The positions of the lamps that bloom at night are in the
lamps list at the top of src/components/sections/Hero.astro, in percent of the photo’s width and
height, and the sun’s position in the evening mask (73% 30%).
Rooms and booking
Section titled “Rooms and booking”Each room has a page with its key fob (the room number), size, beds, sleeps, view, short features such
as “Step-free” or “Dogs welcome”, what’s in the room, the from price a night, two photos and questions;
search engines get it as a schema.org HotelRoom with an offer. Request this room opens the booking
request with the room filled in; Check availability shows the calendar.
Booking works by request, as most small hotels prefer: the guest sends their dates, nights, guests, a room and an offer or voucher; the request is emailed to you and you reply with the price. Availability comes from Cal.com (it loads on click; until it’s connected the page shows a preview of the calendar). The deposit that holds a room is paid with Stripe (a one-time Price id) or Lemon Squeezy (a variant id) in Pages → Book page → Deposit. The site never confirms a booking by itself.
Dining, spa, offers, vouchers and weddings
Section titled “Dining, spa, offers, vouchers and weddings”Menus are lists of courses with dishes and prices, set like a printed menu with dotted leaders. Each offer has a price on a key fob, for whom, when and what’s included; its button opens the booking request with the offer named. Gift vouchers are one-time payments (a Stripe Price id or Lemon Squeezy variant id on each voucher). The weddings page has the spaces with their capacities and an enquiry form that is emailed to you.
The map
Section titled “The map”The visit page and the home section “Getting here” show a map of the streets round the hotel, drawn
from OpenStreetMap in your colors, with the sea (from the
coastline), a pin, your address and directions links. It is part of the page (no embed, no cookies) and
follows the theme and your accent. To draw your own, put your coordinates in map.config.json and run
pnpm map -- fetch.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Availability | Book page and every room, loads on click; a preview of the calendar until connected | Cal.com |
| Deposit and gift vouchers | Book page (deposit) and vouchers page, one-time | Stripe or Lemon Squeezy |
| Letters by email | Home and journal pages, with a welcome email | Supabase or Mailchimp |
| Booking requests, event enquiries, messages | Book, weddings and visit pages; to the email in Site settings | Resend |
| AI chat | Every page; answers about rooms, prices from, dining, the spa, offers and getting here; never says a room is free | Claude or OpenAI |
| Returning guests’ page | Journal | Clerk |
| Search | ⌘K or the search button: rooms, pages, journal | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics, PostHog |
| Photos | Production builds | Cloudinary (optional) |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Hero, Rooms (cards whose photos open like doors), Numbers (beside a tide gauge, the sea rising as it scrolls in), A photo and a story (used for dining and the spa: the photo drifts like a camera on a slider and warms to lamplight), Offers, Journal, Letters (a rose clay band), Getting here (the map) and Closing call (the lit front door beside the headline, dark in both themes).
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (sea
glass: buttons, marks, tide lines), the second (candle gold: stars, small capitals, the clock and the
glow of the lamps) and the third (rose clay: the favourite offer, the returning guests badge, the
letters band). Buttons and rose clay are darkened until their white text is readable, candle gold is
adjusted for each theme; a color that can’t get there stops the build with a message. Brand also sets
the fonts and the corners. The site opens in its dark theme even when the visitor’s system is light; the
toggle switches to the day (linen and ink) and the browser remembers it.
Languages
Section titled “Languages”Haven is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Full house: tonight every room in the house is taken and every party at the desk wants something: a sea view, no stairs, a dog with them, beds for four, a quiet room, to be next to friends or well away from someone. Tap a guest, then a room (or Tab and Enter), then hand out the keys: unhappy guests show what went wrong, and every check that fails costs 20 points. Every night can be done; three nights, 4, 6 and 8 rooms; 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/)./llms.txtlists your pages, rooms and the journal for AI assistants, in every language.- Pages carry JSON-LD: the hotel as a
Hotel(address, position, check-in and check-out, price range, hours, rating), rooms asHotelRooms with offers, the restaurant with its menus, offers, vouchers and the deposit as offers, 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 map round map.config.json from OpenStreetMappnpm cms sanity schema|seed # move content to Sanity (see Content → Sanity)