Skip to content

Tint

Tint is a site for a house painter: interior and exterior painting, cabinet refinishing, colour consultations, drywall and plaster repair, and deck and fence staining. It is confident and colourful, built like a paint card: the home page opens on a short silent film of a roller laying paint across a limewashed wall, edge to edge on every screen, with the headline on a painted stroke across it and the phone number and a free estimate right under it. Behind every page a limewashed wall with brushed-out sample patches drifts as you scroll; the colours are damson, verdigris and plaster pink on warm limewash. The demo is a fictional business, Larkspur Painting Co.

Tint 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 (a room, packages, how a job runs, booking, deposits and gift cards, 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 projects, questions, photo) Content → Services
Projects (where, when, what was painted, days, coats, cost, colour schedule, 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, guarantee Pages → Legal

In headlines, words wrapped in *stars* get a band of colour rolled on behind them as they scroll into view, as in “Most of the work is *under the paint*”. On the opening’s stroke they turn plaster pink.

The home page’s first section is the film. Its texts are yours: the status line (“Booking spring exteriors”), the small line, the headline and the lead (all three on the painted stroke), two buttons (make the first one your phone number as a tel: link and it gets a phone icon) and up to three facts under them on chips of the tint ladder (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. 62% 45%).
  • Film: a short silent MP4 in public/media/ (about 2 MB, 1280 wide), e.g. /media/hero.mp4. It starts loading only after the page has, fades in over the photo, plays once and stays on its last frame. Leave it empty to show the photo only. Visitors who prefer reduced motion or save data see the photo.

Every text on the opening sits on something solid (the stroke, the status capsule, the chips, the buttons), so you can swap in a brighter or darker film without checking the contrast again. On load a roller rolls the stroke on from the left.

Each service card is a paint chip with a band in one of the three colours: damson, verdigris or plaster pink. Projects carry their colour schedule: up to five named colours (e.g. “Body: Lichen”, with a hex value near the paint), shown as a strip of swatches on the card and as named chips on the project’s page. Those colours are your client’s, not your site’s, so they can be anything.

The prices page holds a room’s price on a big paint chip with its small print (trim, repairs, paint, the estimate visit), up to four packages (mark one as the popular one), how a job runs as steps beside a wall in section whose layers go on one by one (also on the home page), booking an estimate visit with Cal.com, and deposits and gift cards 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 Tint) 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 an estimate visit Prices page, loads on click; a preview of the calendar until connected Cal.com
Deposits and gift cards Prices page (one-time prices) Stripe or Lemon Squeezy
Colour 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 “from”, and never gives instructions for removing old paint, high ladders or spraying 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 painted stroke), Services (paint-chip cards that swing out like a fan deck), How a job runs (a wall in section, layer by layer), Recent projects (with their colour schedules), Numbers (on the tint ladder, palest to deepest), The area on a map, Guides, Colour notes by email and Closing call (a dark band with sample patches and a photo taped to it). With reduced motion nothing moves.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (damson: the painted stroke, buttons, links and the tint ladder), the second (verdigris: dark fills, rules and numbers) and the third (plaster pink: the band behind marked words, chips and light fills). The accent and verdigris are darkened until white text on them is readable, the pink is lightened until dark text on it is, and every chip of the tint ladder gets the text colour that reads on it; a color that can’t get there stops the build with a message. Brand also sets the fonts and the corners (crisp, like a taped edge, or soft with pill buttons). The site opens on the limewash day theme even when the visitor’s system is dark; the toggle switches to the night, and the browser remembers the choice. The header strip, the tab bar and the dark painted bands look the same in both.

Tint is ready for more languages: see Languages.

A small game, Feature wall: a client’s design for a feature wall is pinned up, a grid of squares in two to four colours, and the wall in front of you is primer white. Pick a paint (tap a pot, or keys 1–4) and roll a whole row or column with it (tap the roller at its end, or the arrow keys and Enter). A stroke covers everything under it, so the order is the puzzle; U undoes a stroke and R strips the wall. Each wall scores 100 × the fewest strokes ÷ yours (the fewest is worked out exactly for every wall). Three walls, bigger and with more colours each time; 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 HousePainter with the areas it serves and its packages, services as Services with their price, projects as CreativeWorks, how a job runs 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).