Char
Char is a site for a steakhouse or grill restaurant: steakhouses, grill rooms, smokehouses and BBQ joints, grill bars, asado and churrasco places. It is set in a dark dining room by firelight: warm soot with a faint oak grain and the glow of the hearth, ember red, brass and claret, a high-contrast serif and a glass pill nav. The home page opens on a full-bleed photo of the room with smoke drifting through a shaft of light and embers rising, the restaurant’s name arched over the kind like a sign on the window, the rating, one line, Book a table and Call side by side, and “Walk-ins welcome” with the address. As you scroll, a steak is seared step by step. The demo is a fictional restaurant, Ash & Oak.
Char 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) |
| Menu (sections, dishes, prices, weights, dietary marks, doneness scale, allergens) | Pages → Menu page |
| Signature dishes (a page each: story, price and weight, how it’s cooked, pairing, questions, photo) | Content → Signature dishes |
| Reserve (Cal.com booking, reservation request, phone, sittings, policies, questions) | Pages → Reserve page |
| Private dining (rooms, set menus, what’s included, enquiry form, questions) | Pages → Private dining page |
| Gift cards (cards to buy, how it works, questions) | Pages → Gift cards page |
| Journal | Content → Journal (one post can be members-only) |
| Visit (map, hours, getting here, message form, questions) | Pages → Visit page |
| Name, phone, address, rating, opening hours, cuisine, navigation, profiles | Pages → Site settings |
| Buttons, labels, chat, emails, game texts | Content → Interface texts |
| Privacy, terms, booking policy | Pages → Legal |
In headlines, words wrapped in *stars* are set in italic with a line of embers burning along under
them, as in “Cooked over *oak*”.
The menu
Section titled “The menu”The menu is one page made of sections. Each section has a layout: Dishes (a dish, a dotted leader,
the price), Cuts (the weight beside the name, for the steaks from the hearth) or Drinks (on
claret, for the wine list and cocktails). Each item can carry dietary marks (v, vg, gf, n, explained
in the legend) and link to a signature dish’s own page. Under the menu sits the doneness scale (the
temperatures your steaks reach at the table) and the allergen note. The menu is also published for
search engines and assistants as a schema.org Menu.
The sear
Section titled “The sear”The home section “The sear” pins a drawing of a steak on the grill while you scroll through four steps (Aged, Salt, Fire, Rested; write your own): it is salted, the grill marks burn in, it turns for the crosshatch, flips, moves to the board while the probe climbs to your temperature, and is sliced. Set the probe reading and the doneness label in the section. Without scroll-driven animations or with reduced motion, it shows the sliced steak and all four steps.
Booking, private dining and gift cards
Section titled “Booking, private dining and gift cards”Book a table with Cal.com (it loads on click; until it’s connected the page shows a preview of the calendar with your times). For anything unusual, guests send a reservation request, which arrives in your inbox; the phone number sits beside it. Private dining enquiries arrive the same way. Gift cards are paid with Stripe (one-time Price ids) or Lemon Squeezy (variant ids); without keys the buttons explain how to switch them on.
The map
Section titled “The map”The visit page and the home section “Find us” show a map of the streets round the restaurant, drawn
from OpenStreetMap in your colors, with a pin, your address
and directions links. It is part of the page (no embed, no cookies) and follows the theme and your
accent. To draw your own, put your coordinates in map.config.json and run pnpm map -- fetch.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Book a table | Reserve page, loads on click; a preview of the calendar until connected | Cal.com |
| Gift cards | Gift cards page (one-time prices) | Stripe or Lemon Squeezy |
| Events by email | Home and journal pages, with a welcome email | Supabase or Mailchimp |
| Reservation requests, enquiries, messages | Reserve, private dining and visit pages; to the email in Site settings | Resend |
| AI chat | Every page; answers about the menu, booking, private dining, hours and parking; never promises a dish is allergen-free | Claude or OpenAI |
| Members-only recipe | Journal | Clerk |
| Search | ⌘K or the search button: menu, dishes, pages, journal | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics, PostHog |
| Photos | Production builds | Cloudinary (optional) |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Hero, The sear, Signature dishes, Numbers (on a probe thermometer that fills with heat), Private dining (the room warms up as it scrolls in), Journal, Events by email (a claret band with embers drifting up), Find us (the map and the hours) and Closing call (the fire’s photo beside the headline, dark in both themes).
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent
(ember red: Book buttons, marks), the second (brass: stars, small capitals, rules) and the
third (claret: the wine list, badges, the events band). Buttons and claret are darkened until their
white text is readable, brass is adjusted for each theme; a color that can’t get there stops the build
with a message. Brand also sets the fonts and the corners. The steak and the grill use food colours,
so they stay true whatever accent you pick. The site opens in its dark theme even when the visitor’s
system is light; the toggle switches to the day (linen and ink) and the browser remembers it.
Languages
Section titled “Languages”Char is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Resting: each table’s ticket asks for a steak at a doneness. Steaks of different thickness lie on a grill with a hot and a cool side. Pick one (tap it, or 1–4), flip it (F) so both sides get a crust, move it between the sides (M) and pull it onto the board (P or Enter). It keeps cooking while it rests, more after the hot side and more if it’s thick, so pull it early. A side left down over the heat too long burns; a side that never went down stays pale. Then it’s sliced: up to 100 points a steak. Three services of 2, 3 and 4 steaks; 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, dishes, the whole menu and the journal for AI assistants, in every language.- Pages carry JSON-LD: the restaurant as a
Restaurant(cuisine, price range, hours, reservations) with itsMenuon the menu page, signature dishes asMenuItems, set menus and gift cards as offers, questions as aFAQPage, and each journal post 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).