Sheen
Sheen is a site for a house cleaning business: regular cleaning, deep cleans, move-in and move-out, cleaning after builders, rental turnovers and extras. It is light and calm, built from one picture: low morning sun raking across a polished oak floor in a white limewashed room. The home page opens on that room across the whole screen, a linen curtain breathing in a short film, with the phone number and a price button right on it. Behind every page soft patches of window light drift as you scroll; the colours are olive, butter sunlight and lavender on warm linen. The demo is a fictional business, Wren & Linen Home Cleaning.
Sheen 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, before & after, guides, 404 | Pages → the page’s own entry |
| Prices (standard visit, packages, how a visit works, booking, deposits and gift cards, questions) | Pages → Prices page |
| Contact (price form, towns, map, hours, details, questions) | Pages → Contact page |
| Services (icon, badge colour, price from, how long, what’s included, who it’s good for, questions, photo) | Content → Services |
| Before & after (where, when, what you found, team, time, cost, the two photos, story) | Content → Before & after |
| 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 | Content → Interface texts |
| Privacy, terms, guarantee | Pages → Legal |
In headlines, words wrapped in *stars* are set in the accent with a slanted band of sunlight that slides
in behind them as they scroll into view, as in “Clean enough to *catch the light*.”
The opening
Section titled “The opening”The home page’s first section fills the whole screen on every device. Its texts are yours: the status
line (“Now booking Monday to Saturday”), 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 under them
on wider screens. The picture is one or two files:
- Photo: 16:9 and at least 1920 pixels wide, light and calm in the middle where the text sits. 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.
38% 60%). - Film (optional): a short silent MP4 loop of the same view in
public/media/(1–2 MB, 1280 wide), e.g./media/hero.mp4. It starts loading only after the page has, fades in over the photo and pauses when you scroll past. Leave it empty to show the photo only. Visitors who prefer reduced motion or save data see the photo.
The text sits on a soft veil of linen white that keeps it readable even over a black frame, so the opening stays light in both themes. On load, a squeegee stroke wipes a faint haze off the photo once.
Before & after
Section titled “Before & after”Each story has two photos from the same spot, before you started and when you were done. Keep the camera still between them (a tripod or a mark on the floor) so they line up. On the story’s page, and for the newest story on the home page, the two are laid over each other with a squeegee blade between them: drag it, or use the arrow keys, to compare. As the photo scrolls into view the blade sweeps in to the middle. The other stories show as cards with the “before” tucked into a corner.
Services
Section titled “Services”Each service has a round badge in one of the three colours: olive, butter or lavender. Service photos are wiped clean of a faint haze as they scroll into view and catch a glint of light when you point at them.
Prices, booking and payments
Section titled “Prices, booking and payments”The prices page holds your standard visit on a slanted patch of sunlight with its small print (extra rooms, regular visits, what’s included), up to four packages (mark one as the popular one), how a visit works as a checklist whose ticks draw themselves (also on the home page), booking a free walk-through 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 office 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 office’s coordinates in map.config.json
and run pnpm map -- fetch. detail: "area" (the default in Sheen) 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 walk-through | 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 |
| Cleaning 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 |
| Price form | Contact page; messages go to the email in Site settings | Resend |
| AI chat | On every page, answers about services, prices, before & after and areas; never advises mixing cleaning products | Claude or OpenAI |
| Search | ⌘K or the search button: services, before & after, 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 photo and film), Services (cards with a round badge), Before & after (the newest story to drag and compare, then cards), How a visit works (a checklist that ticks itself), Numbers (set large with a band of sun), The area on a map, Guides, Cleaning notes by email (an olive-black panel) and Closing call (an olive-black band with window light and a photo in a white mount). 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
(olive: buttons, links, marked words, the ticks and the footer’s band), the second (butter sunlight:
the light behind marked words and numbers, the sun patches, fills with dark text) and the third
(lavender: chips and small fills with dark text, and the moonlight of the dark theme). The accent is
darkened until white text on it is readable, butter and lavender are lightened until dark text on them
is; a color that can’t get there stops the build with a message. Brand also sets the fonts and the
corners (rounded with pill buttons, or nearly square). The site opens on the linen day theme even when
the visitor’s system is dark; the toggle switches to dusk, and the browser remembers the choice. The
opening and the olive-black bands look the same in both.
Languages
Section titled “Languages”Sheen is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Wet floor: a room seen from above, furniture on some of the tiles and the door in one wall. Mop every tile, one step at a time (the arrow keys or WASD, a swipe, a tap on the tile next to you, or the on-screen arrows), and leave through the door last. A mopped tile is wet and can’t be stepped on again, so plan the way round: stuck with dry tiles left, you’ve mopped yourself into a corner and the room starts over. Every room is checked to have a way through. Three rooms, bigger each time, 100 points each less 25 per restart; 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, before & after stories and guides for AI assistants, in every language.- Pages carry JSON-LD: the business as a
HouseCleaningServicewith the areas it serves and its packages, services asServices with their price, before & after stories asCreativeWorks, how a visit works 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).
