Razor
Razor is a site for a barbershop, a grooming studio, a single-chair barber or a beard bar, in neo-brutalism. The page is the shop’s wall of white subway tiles, full width, with a black and white checkerboard floor above the footer; on wide screens a barber pole stands at the right edge and its stripes turn as you scroll. Thick ink borders, hard shadows, flat blocks of red, blue and brass and tall signage type. On the home page a “now serving” ticket rolls up to its number, the prices hang on a black letter board, the barbers are trading cards with stats, and a mirror wipes from one step of a haircut to the next as the steps scroll past.
Razor 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) |
| Barbers, services, apprentices, journal, visit, 404 | Pages → the page’s own entry |
| Barbers (role, tagline, since, specialties, card stats, days in, signature cut, portrait) | Content → Barbers |
| Journal posts | Content → Journal |
| Name, description, email, phone, address, navigation, header button, profiles, social picture | Pages → Site settings |
| Buttons, labels, chat, search, emails, game texts | Content → Interface texts |
| Privacy, terms | Pages → Legal |
In headlines, words wrapped in *stars* are set on a brass block, as in “Walk in rough. Walk out
*sharp.*”.
The cut
Section titled “The cut”The cut section keeps a framed mirror on screen while its steps (three to six) scroll past. Each step has a time, a title, a text and a tall photo; as a step comes into view its photo wipes in over the last one in hard steps, and a giant step number sits beside it. Visitors who prefer reduced motion see the last photo.
Prices, gift cards and booking
Section titled “Prices, gift cards and booking”- The price board (Pages → Services page): groups such as Hair, Beard and Extras, each line a name, a price, a time and a note. The services page shows the whole board; the home page’s board shows its first lines.
- Gift cards: turn on “Sell with Stripe Checkout” on a gift card and put a one-time Price id
there; the button then works. Buyers come back to the services page, and the Stripe webhook
(
/api/stripe/webhook) emails them, where you can add your own steps. - Booking a barber: Cal.com, on the services page.
- Barbers: each has a trading card (a colour band with their role, the portrait, up to three stats on the card and up to five on their page), specialties, the days they’re in, and a signature cut.
- Quotes on the home page: only real quotes with their source.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Gift cards | Services page | Stripe |
| Booking a barber | Services page; a preview of the calendar until it’s connected | Cal.com |
| Newsletter and the apprentice list | Home, journal and apprentices pages, with a welcome email | Supabase |
| Contact form | Visit page; messages go to the email in Site settings | Resend |
| AI chat | On every page, answers from your prices, barbers, opening hours, walk-ins and journal | Claude |
| Search | ⌘K or the search button: barbers, journal, services, apprentices, visit | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics |
Sections
Section titled “Sections”The home page is built from these sections, in any order: The opening (with the “now serving” ticket), The cut, The price board, Barbers, Feature (a photo and a text, e.g. hot towel shaves or kids’ cuts), Numbers, Quotes, From the journal, Newsletter sign-up and Closing call.
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the
accent (buttons, links and the red of the pole), the second (blue blocks and the pole’s
blue) and the third (brass blocks, tags and headline highlights). Buttons are darkened until
their white text is readable, the fills are lightened until ink text on them is; a color that
can’t get there stops the build with a message. The site opens in the day theme whatever the
visitor’s system is set to; the night theme, the shop after hours with black tiles and cream
shadows, comes on with the toggle. Brand also sets the fonts (a tall condensed face for headings,
the text font and the label font) and the corners (square or slightly rounded).
Languages
Section titled “Languages”Razor is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Line up: trace the dashed line on a head with the clippers, as closely as you can. Drag along it with a mouse, finger or pen, or hold Space and steer the drifting clippers with ↑ and ↓. Three cuts (a hairline, a beard line, a lightning bolt); points come from how much of the line you covered and how much of your stroke stayed on it. 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, barbers and journal for AI assistants, in every language.- Pages carry JSON-LD: the shop as a
HairSalon, barbers asPersons, services as aService, the apprentices page as aJobPosting, the visit questions as aFAQPage, and each post.
Commands
Section titled “Commands”pnpm dev # local site, editor at /keystaticpnpm build # production buildpnpm 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).