Lido
Lido is a site for a pool service company: weekly pool service, openings and closings, green-to-clean recoveries, repairs and leak detection, equipment and upgrades, and spa and hot tub care. It is sunny and graphic, like a 1950s lido: the home page opens on a short silent film of the floor of a clear pool seen from straight above, edge to edge on every screen, while a pool cover rolls back off the water, with the phone number and a free pool check right under the headline. Every section’s label carries a glazed depth marker (“3 FT”, “4 FT”…) that counts down the page like the markers on a pool deck, and a fine pool-tile grid runs behind every page; the colours are cabana coral, deep-end cobalt and lounger lemon on sun-bleached stone. The demo is a fictional business, Halcyon Pool Co.
Lido 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) |
| Services, projects, guides, 404 | Pages → the page’s own entry |
| Prices (a weekly visit, plans, a visit step by step, booking, deposits and gift cards, questions) | Pages → Prices page |
| Contact (pool check form, towns, map, hours, details, questions) | Pages → Contact page |
| Services (icon, colour, price from, how long, what’s included, typical jobs, questions, photo) | Content → Services |
| Projects, the pool stories (where, when, what we did, time, visits, cost, the water before and after, photo, story) | Content → Projects |
| Guides (one can be for members only) | Content → Guides |
| Name, phone, address, insurance, navigation, header button, profiles | Pages → Site settings |
| Buttons, labels, chat, emails, game texts, the depth marker’s unit | Content → Interface texts |
| Privacy, terms, guarantee | Pages → Legal |
In headlines, words wrapped in *stars* get a lane rope: a line of coral, white and cobalt floats pays out
under them as they scroll into view, as in “Back to blue, *pool by pool*”. On the opening they turn lemon.
The opening film
Section titled “The opening film”The home page’s first section is the film. Its texts are yours: the status line on a glazed tile (“Now
booking spring openings”), the small line, the headline, the lead, two buttons (make the first one your
phone number as a tel: link and it gets a phone icon) and up to three facts on glazed tiles under them
(wide screens). The picture is two files:
- Photo: the film’s first frame, 16:9 and at least 1920 pixels wide. It shows at once and is what
search engines and slow phones see. Set Photo focus to the part that should stay in view on a
narrow screen (e.g.
50% 50%). - Film: a short silent MP4 in
public/media/(about 2 MB, 1280 wide), e.g./media/hero.mp4. It starts loading only after the page has, fades in over the photo and loops (make it play forward and then backward, so the loop has no cut). Leave it empty to show the photo only. Visitors who prefer reduced motion or save data see the photo.
The copy sits on a deep-end plate, a cobalt-black shade that reaches well beyond the text, so white text stays readable over any frame, even a white one; the buttons and tiles are solid. On load a slatted pool cover rolls back off the water (not with reduced motion).
Services and pool stories
Section titled “Services and pool stories”Each service card carries a waterline course of small tiles in one of the three colours (coral, cobalt or lemon) with its number on a white tile and its drawing. Pool stories carry the water’s readings, before and after (up to four, e.g. “Free chlorine: 0 ppm → 3 ppm”): two on the card, all of them on the story’s page.
Prices, booking and payments
Section titled “Prices, booking and payments”The prices page holds a weekly visit’s price on a big cobalt tile with its small print (larger pools, a spa, filter cleans, the pool check), up to four plans (mark one as the popular one), a weekly visit step by step beside a water test strip whose pads develop their colours as you scroll (also on the home page), booking a free pool check with Cal.com, and deposits and gift cards you take with Stripe or Lemon Squeezy: each one gets 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.
The map of the area
Section titled “The map of the area”The map is drawn from OpenStreetMap in your colours, with a
pin on your shop and a ring for the area you cover. It is part of the page (no embed, no cookies) and
follows the theme and your accent. To draw your own, put your shop’s coordinates in map.config.json and
run pnpm map -- fetch. detail: "area" (the default in Lido) draws the main roads, railways, water and
woods of a whole district, and Contact page → Map → Radius sets the ring; detail: "streets" draws the
streets and buildings round one address instead.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Book a free pool check | Prices page, loads on click; a preview of the calendar until connected | Cal.com |
| Deposits and gift cards | Prices page (one-time prices) | Stripe or Lemon Squeezy |
| Pool notes by email | Home and guides pages, with a welcome email | Supabase or Mailchimp |
| Members-only guides | A guide marked members only shows its text after signing in | Clerk |
| Pool check form | Contact page; messages go to the email in Site settings | Resend |
| AI chat | On every page, answers about services, prices, pool stories and areas; gives prices only as “from”, never gives chemical doses or tells anyone to mix chemicals | Claude or OpenAI |
| Search | ⌘K or the search button: services, pool stories, guides, prices, contact | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, PostHog, Google Analytics |
| Photos | Served from your Cloudinary account when it is set | Cloudinary |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Opening (the film and the pool cover), Services (cards with a waterline course), A weekly visit (a test strip, pad by pad), Pool stories (with the water before and after), Numbers (on glazed depth tiles along a stone coping), The area on a map, Guides, Pool notes by email and Closing call (the deep end with a lane line and a photo in a stone coping). With reduced motion nothing moves.
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (coral:
buttons, links and marked words, the lane-rope floats), the second (cobalt: the deep bands, the hero’s
plate, the depth tiles’ lettering and the depth scale) and the third (lemon: chips, the readings after
and light fills). The accent and cobalt are darkened until white text on them is readable, the lemon is
lightened until dark text on it is, and every shade of the depth scale gets the text colour that reads on
it; a color that can’t get there stops the build with a message. Brand also sets the fonts and the corners
(the soft square of a pool tile, or round with pill buttons). The site opens on the stone day theme even
when the visitor’s system is dark; the toggle switches to the pool after dark, and the browser remembers
the choice. The header strip, the tab bar and the deep bands look the same in both. The depth markers’ unit
(“FT”, or “M” if you work in metres) is in Content → Interface texts.
Languages
Section titled “Languages”Lido is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Make waves: leaves float on a pool seen from above and the skimmer’s mouth is a gap in one wall. You can’t touch the leaves: tap the water (or move the ring with the arrow keys and press Enter or Space) to drop a ripple, which pushes every leaf it passes away from where it fell, harder close by. Herd every leaf into the skimmer with the ripples you have. Each pool scores 20 per leaf skimmed and 10 per ripple left; three pools, with more leaves and the skimmer on another wall each time. Every pool is checked to be solvable before it is dealt, and 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, services, pool stories and guides for AI assistants, in every language.- Pages carry JSON-LD: the business as a
HomeAndConstructionBusinesswith the areas it serves and its plans, services asServices with their price, pool stories asCreativeWorks, a weekly visit as aHowTo, questions as aFAQPage, and each guide 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)In the EmDash variant: npm run dev, npm run deploy (Cloudflare) and npm run emdash:schema
(after changing the content model).
