Slate
Slate is a site for a roofer or a roofing company: slaters and tilers, flat-roof specialists, leadworkers, gutter and fascia firms, chimney repair. It is drawn like a set of architect’s sheets under a sky that changes as you scroll: hairline cards, dimension lines, labels in a mono, a fine serif for headings, slate grey with weathered copper (verdigris), copper and sky blue. On the home page a house is drawn in cross-section and, as you scroll, its roof is built layer by layer: the rafters rise, the membrane rolls out, the battens snap on, the slates are laid course by course from the eaves up, the ridge goes on, the flashing is dressed round the chimney and the gutters are fixed. Then a storm rolls in, rain falls, and the water runs off the slates into the gutter and down the pipe while the room underneath stays dry, with the fire and the lamp lit. The demo is a fictional firm, Hale & Ridge Roofing.
Slate 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, jobs, advice, 404 | Pages → the page’s own entry |
| Prices (the survey, typical jobs and prices, how a job works, booking, reports and deposits, questions) | Pages → Prices page |
| Contact (survey form, areas, map and its ring, hours, details, questions) | Pages → Contact page |
| Services (icon, price from, how long, what’s included, typical jobs, questions, photo, colour) | Content → Services |
| Jobs (where, when, time, cost, before and after photos, story) | Content → Jobs |
| Advice (one can be members only) | Content → Advice |
| 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 dimension line under them, as in
“A roof that keeps *the weather out*”.
The roof
Section titled “The roof”The home page’s opening (the Roof section) has eight captions, one per layer, in the order the drawing builds them: rafters, membrane, battens, slates, the ridge, the flashing, the gutters and the storm. Change the words to your own (keep the order, since the drawing doesn’t change), the pitch written beside the eaves and the scroll hint. With reduced motion, or in a browser without scroll-driven animations, the finished roof stands in the rain with the last caption.
Jobs: before and after
Section titled “Jobs: before and after”Each job has a before and an after photo of the same view. On the cards (home page, jobs page, a service’s page) the after photo wipes in as the card scrolls past; on the job’s own page a slider lets visitors compare them (drag, or the arrow keys). Take both photos from the same spot.
Prices, booking and payments
Section titled “Prices, booking and payments”The prices page holds the survey set large (free, in the demo) with its small print, up to four typical jobs with their prices (mark one as the most asked-for), how a job works as steps up a ladder (also on the home page), booking a survey with Cal.com, and survey reports and deposits paid online with Stripe or Lemon Squeezy: each one gets a one-time Price id (or a Lemon Squeezy variant 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 you cover
Section titled “The map of the area you cover”The map is drawn from OpenStreetMap in your colors, with a
pin on your yard and a dashed ring for the area you cover (Contact page → Map → Radius, in km; 0
hides it). It is part of the page (no embed, no cookies) and follows the theme and your accent. To
draw your own area, put your yard’s coordinates in map.config.json and run pnpm map -- fetch.
detail: "area" (the default in Slate) draws the main roads, railways, water and woods of a district;
make size about four times your radius in each direction (30,000 × 15,000 m for 8 km). 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. See
Features for each service.
| Feature | Where |
|---|---|
| Book a survey | Prices page, loads on click; a preview of the calendar until connected (Cal.com) |
| Survey reports and deposits | Prices page (Stripe or Lemon Squeezy) |
| Roof care by email | Home and advice pages, with a welcome email (Supabase or Mailchimp) |
| Survey form | Contact page; messages go to the email in Site settings (Resend) |
| AI chat | On every page, answers about services, prices, jobs and areas; never tells anyone to go up on a roof (Claude or OpenAI) |
| Members-only advice | An article marked “Members only” shows its text to signed-in members (Clerk) |
| Search | ⌘K or the search button: services, jobs, advice, prices, contact (built in, or Algolia) |
| Analytics | Every page; Google Analytics only after consent (Plausible, Umami, PostHog, Google Analytics) |
| Photos | Served from Cloudinary when a cloud name is set |
Sections
Section titled “Sections”The home page is built from these sections, in any order: the Roof (the opening), Services (cards cut like slates, laid in courses), Recent jobs (before and after), How a job works (steps up a ladder), Numbers (along a dimension line), The area covered (the map), Advice, Roof care by email and the Closing call (a storm band with rain falling past the photo).
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent
(verdigris: buttons, links, marks, the flashing), the second (copper: a warm fill, the chimney
pots, the warm room) and the third (sky: the sky behind the page, rain, a cool fill). Buttons are
darkened until their white 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. Brand also sets the three fonts
(headings, text, labels) and the corners. The site opens in the day theme even when the visitor’s
system is dark; the toggle switches to the night sky, and the browser remembers the choice.
Languages
Section titled “Languages”Slate is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Leak hunt: a roof of slates hides a few cracked ones. Lift a slate (tap, or the arrow keys and Enter): a sound one shows how many cracked slates touch it, and since the slates are laid with their joints broken, each one touches six. Lift a cracked one and the rain gets in, which costs a bucket. Mark the slates you suspect (the Mark switch, a right-click, a long press or F). Three roofs, more cracked slates each, three buckets for the whole game; the first slate on each roof is always sound. 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, jobs and advice for AI assistants, in every language.- Pages carry JSON-LD: the business as a
HomeAndConstructionBusinesswith the areas it serves and its typical jobs, services asServices with their price, jobs asCreativeWorks, how a job works as aHowTo, questions as aFAQPage, and each article 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).