Trowel
Trowel is a site for a concrete and masonry contractor: driveways and flatwork, stamped patios, foundations and slabs, retaining walls, brick and stone, and repair and levelling. It is exact and calm, like an architect’s book on board-formed concrete: the home page opens on a short silent film of a slab being screeded, shot low at slab level, edge to edge on every screen, with the headline standing on a concrete slab under a spirit level and the phone number and a free estimate right under it. Cards, photos and buttons have chamfered corners, the faint joints and tie holes of board-formed concrete run behind every page, and the colours are layout magenta, wet graphite and survey lime on pale concrete. The demo is a fictional business, Haldane Concrete & Masonry.
Trowel 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 (flatwork per square foot, packages, a pour step by step, booking, deposits and sealing 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, size, time, cost, the batch ticket, 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* are screeded: a lime band on a graphite straightedge is pulled
under them as they scroll into view, as in “Poured this year, *ticket and all*”.
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 lime tag (“Booking
spring pours”), 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 form tags under the slab (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.
55% 55%). - Film: a short silent MP4 in
public/media/(about 1 to 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 stands on the slab, an opaque panel of smooth concrete (light by day, graphite at night), so it reads the same over any frame of any film. On load the spirit level’s bubble drifts and settles in the middle, and a straightedge sweeps across the slab once, rough ahead of it and smooth behind (not with reduced motion).
Services and projects
Section titled “Services and projects”Each service card shows its photo, which has its forms stripped as the card scrolls into view (plywood boards drop away), and a band in one of the three colours with its number and its drawing. Projects carry a batch ticket, like the slip that comes with each truck from the concrete plant: up to eight lines such as “Mix: 4,000 PSI, fibre”, “Slump: 4 in” or “Cured: 7 days wet”. Cards show the first three lines; the project’s page shows them all beside the story.
Prices, booking and payments
Section titled “Prices, booking and payments”The prices page holds flatwork’s price per square foot on a graphite slab with its small print (tear-out, stamped or coloured, the smallest job, the estimate), up to four packages (mark one as the popular one; prices can be ranges like “$8,500–$14,000”), a pour step by step beside a slab in cross-section that is laid layer by layer as you scroll (also on the home page), booking a free estimate with Cal.com, and deposits and sealing visits 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 yard 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 yard’s coordinates in map.config.json and
run pnpm map -- fetch. detail: "area" (the default in Trowel) 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 estimate | Prices page, loads on click; a preview of the calendar until connected | Cal.com |
| Deposits and sealing visits | 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 gives engineering advice | 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 |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Opening (the film and the slab), Services (cards with their forms stripped), How a pour goes (the slab’s cross-section, layer by layer), Projects (with their batch tickets), Numbers (as test cylinders that fill as they scroll in), The area on a map, Guides, Care notes by email and Closing call (a board-formed graphite wall with a photo in a concrete frame). 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
(magenta: buttons, links and marked words), the second (graphite: the deep bands, the plates and dark
fills) and the third (lime: the screed lines, the status tag, chips and light fills). The accent and
graphite are darkened until white text on them is readable and the lime 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
(chamfered, cut at 45°, or square). The site opens on the pale concrete day theme even when the visitor’s
system is dark; the toggle switches to wet concrete after dark, and the browser remembers the choice. The
header strip, the tab bar and the deep bands look the same in both.
Languages
Section titled “Languages”Trowel is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Cut and fill: a slab from above before the screed, with high spots that carry extra barrows of concrete, low spots that are short, and a column footing or two in the way. Tap a high spot and then a low spot (or the arrow keys and Enter) to wheel one barrow across: it goes the shortest way round the footings and every square costs a step. Level the slab, then screed it. Each slab scores 100 × the fewest barrow-steps ÷ yours; the fewest is worked out exactly, and a slab is only dealt when wheeling each barrow to the nearest hollow is not the best plan. Three slabs, each bigger; U undoes a barrow and R starts the slab over. 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, projects and guides for AI assistants, in every language.- Pages carry JSON-LD: the business as a
HomeAndConstructionBusinesswith the areas it serves and its packages (price ranges as a minimum and a maximum), services asServices with their price, projects asCreativeWorks, a pour step by step 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).
