Tumbler
Tumbler is a site for a locksmith: emergency lockouts, lock changes and upgrades, key cutting, safes, smart locks and security surveys for homes and small businesses. It is drawn edge to edge like an engineering drawing: drafting paper with a fine blueprint grid and key blanks dimensioned at the sides, machined brass, blued steel and a signal red kept for the emergency line, and a wide engraved typeface. On the home page a pin-tumbler lock in cross-section opens as you scroll: the key slides in, every pin rides up and down its cuts and settles at the shear line, the plug turns, the bolt draws back and the door swings open into warm light. The demo is a fictional business, Shearline Locksmiths.
Tumbler 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, guides, 404 | Pages → the page’s own entry |
| Prices (call-out rate, packages, how a call-out works, booking, deposits and vouchers, questions) | Pages → Prices page |
| Contact (quote form, areas, map, hours, details, questions) | Pages → Contact page |
| Services (icon, nameplate colour, price from, how long, what’s included, typical jobs, questions, photo) | Content → Services |
| Jobs (where, when, called, on site in, time, cost, photo, story) | Content → Jobs |
| 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 brass with a fine double rule engraved under them,
as in “Locked out? *Let’s get you in.*”.
The opening lock
Section titled “The opening lock”The home page’s first section is the lock. Its texts are yours: the headline, the lead, two buttons
(make the first one your emergency number as a tel: link and it turns signal red with a phone icon),
the scroll hint, the label of the shear line and five captions, one for each step (the key goes in, the
pins meet the shear line, the plug turns, the bolt draws back, the door opens). The drawing itself is
in src/components/sections/Lock.astro: the key’s cuts, the pins and when each step happens are at the
top, and the motion of every pin is worked out from the key’s profile when the site builds. With
reduced motion the lock stands still with the key in and the pins at the shear line.
Services and jobs
Section titled “Services and jobs”Each service has a nameplate in one of the three colours: brass, blued steel, or signal red (keep red for the emergency service). Jobs are shown as work orders: when the call came in, how soon you were on site, the time on site and the cost, with a “Done” stamp.
Prices, booking and payments
Section titled “Prices, booking and payments”The prices page holds your call-out rate on a brass plate with its small print (evenings, nights, after the first half hour, parts), up to four packages (mark one as the popular one), how a call-out works as steps cut into a key (also on the home page), booking a visit with Cal.com, and deposits and gift vouchers 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 workshop
Section titled “The map of the workshop”The map is drawn from OpenStreetMap in your colours, with a
pin on your workshop. It is part of the page (no embed, no cookies) and follows the theme and your
accent. To draw your own, put your workshop’s coordinates in map.config.json and run
pnpm map -- fetch. detail: "streets" (the default in Tumbler) draws the streets and buildings round
one address; detail: "area" draws the main roads, railways, water and woods of a whole district, and
Contact page → Map → Radius then adds a ring for the area you cover.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Book a visit | Prices page, loads on click; a preview of the calendar until connected | Cal.com |
| Deposits and gift vouchers | Prices page (one-time prices) | Stripe or Lemon Squeezy |
| Guides 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 |
| Quote form | Contact page; messages go to the email in Site settings | Resend |
| AI chat | On every page, answers about services, prices, jobs and areas; gives the emergency number first and never explains how to open a lock that isn’t yours | Claude or OpenAI |
| Search | ⌘K or the search button: services, jobs, 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 lock), Services (engraved plates), How a call-out works (steps cut into a key that slides in), Recent jobs (work orders), Numbers (on a caliper whose jaw slides along), The workshop on a map, Guides, Guides by email (a steel plate with a combination dial) and Closing call (a blued-steel band). 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
(machined brass: buttons, plates, the shear line, marks), the second (blued steel: dark fills) and
the third (signal red: the emergency line). Brass is lightened until dark text on it is readable,
steel and red are darkened until white 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. The site opens on the drafting paper even when
the visitor’s system is dark; the toggle switches to blued steel, and the browser remembers the choice.
Languages
Section titled “Languages”Tumbler is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Cut the key: a lock’s code is hidden. Set the depth of each cut on a key blank (tap a cut, then Deeper or Shallower, or the arrow keys) and try it: the lock only tells you how many pins reached the shear line, never which ones. Work out the code before the blanks run out. Three locks of three, four and five pins; a lock opened scores ten points for every blank left, 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, jobs and guides for AI assistants, in every language.- Pages carry JSON-LD: the business as a
Locksmithwith the areas it serves and its packages, services asServices with their price, jobs asCreativeWorks, how a call-out 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).