Skip to content

Eave

Eave is a site for a gutter contractor: seamless gutters, half-round and copper gutters, gutter guards, cleaning and flushing, downspouts and drainage, and repair and re-pitching. It is calm, wet and exact: the home page opens on a short film of rain sheeting off a roof into a clean gutter, edge to edge on every screen, with the headline on a panel hung like a gutter (water runs along its top edge and down a downspout on load) and the phone number and a free estimate right under it. Cards, photos and buttons are square at the top and rounded at the foot, like a half-round gutter seen end on, a fine rain slants behind every page, and the colours are forest green, storm blue and copper on a pale overcast sky. The demo is a fictional business, Larkin Gutter Co.

Eave 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)
Services, projects, guides, 404 Pages → the page’s own entry
Prices (the price per foot, packages, a gutter going up step by step, booking, deposits and visits, questions) Pages → Prices page
Contact (estimate 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 (where, when, what we did, the run, time, cost, the run sheet, 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 Content → Interface texts
Privacy, terms, warranty Pages → Legal

In headlines, words wrapped in *stars* get a stream run under them: a small channel fills with water from the left as they scroll into view and a drop gathers at its end, as in “Hung this year, *run sheet and all*”.

The home page’s first section is the film. Its texts are yours: the status line on a copper chip (“Booking fall installs”), 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 white tags hung under the panel (wide screens).

  • Photo: 16:9 and at least 1920 pixels wide, ideally the film’s first frame. It shows at once and is the page’s largest image. Set Photo focus to the part that should stay in view on a narrow screen (e.g. 40% 60%).
  • Film: a short, silent MP4 in public/ (about 1 MB, 1280 wide), e.g. /media/hero.mp4, made to loop without a cut. It loads after the page, fades in over the photo, pauses when you scroll past and never plays with reduced motion or a data saver. Leave it empty for the photo alone.

The copy stands on the gutter panel, an opaque panel (pale by day, storm blue at night) square at the top and rounded at the foot, so it reads the same over any frame of the film. A length of gutter runs along its top edge and a downspout down its right side; on load water runs along one and down the other, and a drop falls from the outlet now and then. With reduced motion nothing moves.

Each service card’s photo is rinsed as the card scrolls into view: a sheet of water runs down over it and leaves it clear; then a band in one of the three colours with its number and its drawing. Projects carry a run sheet, the spec sheet the crew works from, with the gutter’s fall drawn down its edge and up to nine lines such as “Profile: K-style, seamless”, “Pitch: ¼ in per 10 ft” or “Hangers: Hidden, 24 in apart”. Cards show the first three lines; the project’s page shows them all beside the story.

The prices page holds the price per foot on a big storm-blue gutter seen end on, with its small print (taking the old gutters off, downspouts, the smallest job, the estimate), up to four packages (mark one as the popular one; prices can be ranges like “$2,200–$3,600”), a gutter going up step by step beside the eave of a house drawn from the front that is built stage by stage as you scroll (measured, rolled, hung, pitched, the downspout, the hose test; also on the home page), booking a free estimate with Cal.com, and install deposits, cleaning visits and leak calls 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 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 Eave) 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.

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

Feature Where Service
Book a free estimate Prices page, loads on click; a preview of the calendar until connected Cal.com
Install deposits, cleaning visits and leak calls Prices page (one-time prices) Stripe or Lemon Squeezy
Care 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
Estimate form Contact page; messages go to the email in Site settings Resend
AI chat On every page, answers about services, prices, projects and areas; gives prices only as ranges or “from”, never settles permits or drainage rules for anyone and never tells anyone to climb a ladder in the wet Claude or OpenAI
Search ⌘K or the search button: services, projects, 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

The home page is built from these sections, in any order: Opening (the film and the gutter panel), Services (cards rinsed as they scroll in), How a gutter goes up (the eave of a house drawn from the front, built stage by stage), Projects (with their run sheets), Numbers (in rain gauges that fill as they scroll in), The area on a map, Guides, Care notes by email and Closing call (a storm-blue band in the rain with a photo in a copper frame). With reduced motion nothing moves.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (forest green, the classic colour of a seamless gutter: buttons, links, marked words and their streams by day), the second (storm blue: the deep bands, the plates, dark fills and the night theme) and the third (copper: chips, the status line, light fills and the copper of the drawings). The accent and storm blue are darkened until white text on them is readable and the copper is lightened until dark text on it is; a color that can’t get there stops the build with a message. Brand also sets the fonts and the corners (half-round, square at the top and rounded at the foot, or square). The site opens on the overcast day theme even when the visitor’s system is dark; the toggle switches to rain at night, and the browser remembers the choice. The header strip, the tab bar and the deep bands look the same in both.

Eave is ready for more languages: see Languages.

A small game, Re-pitch: a sagging gutter on a fascia board in the rain, hung on a row of hangers at uneven heights, and water standing in the dips. Set as few hangers as you can higher or lower so every drop runs to the outlet: down to the right, down to the left, or, in the last gutter, from a high point in the middle down to an outlet at each end. Drag a hanger up or down (or pick one with ← → and set it with ↑ ↓, or use the buttons); the water shows live where it still ponds. Run the hose test (the button, Enter or T) when you think it drains; U undoes and R starts over. Each gutter scores 100 × the fewest hangers that must move ÷ the hangers you moved; the fewest is worked out exactly, and a gutter is only dealt when the obvious fix (walking from the high end and dropping every hanger that sits higher than the one before) moves more. Three gutters, of 8, 10 and 12 hangers. 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, services, projects and guides for AI assistants, in every language.
  • Pages carry JSON-LD: the business as a HomeAndConstructionBusiness with the areas it serves and its packages (price ranges as a minimum and a maximum), services as Services with their price, projects as CreativeWorks, a gutter going up step by step as a HowTo, questions as a FAQPage, and each guide as a BlogPosting.
Terminal window
pnpm dev # local site, editor at /keystatic
pnpm build # production build
pnpm map -- fetch # draw the map round map.config.json from OpenStreetMap
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).