Skip to content

Hinge

Hinge is a site for a garage door company: new garage doors, spring replacement, openers, cable, roller and off-track repairs, carriage-house and custom doors, and tune-ups. It is warm, mechanical and exact: the home page opens on a short film of a garage door rising at night, warm light spilling across a wet driveway, edge to edge on every screen, with the headline on a door panel that lifts off its seal on load (a line of warm light opens under it) and the phone number and a free quote right under it. Cards, photos and buttons have coved corners, each scooped inwards like the corner of a raised door panel, the faint ribs of a sectional door run behind every page, and the colours are porch amber, midnight petrol and sodium yellow on pale concrete. The demo is a fictional business, Bellamy Garage Doors.

Hinge 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 (the service call, packages, a door going in step by step, booking, deposits and visits, questions) Pages → Prices page
Contact (quote 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, the door’s size, time, cost, the door sheet, 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* get the light under a door: a line of warm light opens under them from the middle as they scroll into view and a soft glow spills down from it, as in “Fitted this year, *door sheet and all*”.

The home page’s first section is the film. Its texts are yours: the status line on a sodium-yellow chip with a small blinking light (“Same-day spring repairs”), 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 dark keypad tiles under the panel (wide screens).

  • Photo: 16:9 and at least 1920 pixels wide, ideally the film’s first frame. It shows at once and is the page’s largest image. Set Photo focus to the part that should stay in view on a narrow screen (e.g. 50% 55%).
  • Film: a short, silent MP4 in public/ (about 1 MB, 1280 wide), e.g. /media/hero.mp4, made to loop without a cut. The demo’s film plays forward and then backward, so the door rises and comes down again. It loads after the page, fades in over the photo, pauses when you scroll past and never plays with reduced motion or a data saver. Leave it empty for the photo alone.

The copy stands on the door panel, an opaque panel (pale by day, midnight petrol at night) with coved corners and the faint joints of a sectional door, so it reads the same over any frame of the film. On load it lifts a little off its seal, and a line of warm light opens under it and spills down over the film. With reduced motion it simply stands lifted.

Each service card’s photo sits behind a garage door that rolls up as the card scrolls into view, its four sections lifting one after another; then a band in one of the three colours with its number and its drawing. Projects carry a door sheet, the order sheet the crew works from, with the door drawn down its edge and up to nine lines such as “Size: 16 × 7 ft, two-car”, “Insulation: R-16 polyurethane” or “Cycles: 20,000”. Cards show the first three lines; the project’s page shows them all beside the story.

The prices page holds the service call on a door of its own (petrol, four grooved sections, a line of light under it), with its small print (springs, openers, evenings and Sundays, the quote), up to four packages (mark one as the popular one; prices can be ranges like “$1,650–$3,400”), a door going in step by step beside a garage opening drawn from inside that is built stage by stage as you scroll (measured, the tracks, the sections from the floor up, the spring on its shaft, the opener, the safety eyes; also on the home page), booking a free quote with Cal.com, and install deposits, tune-ups and spring repairs 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 Hinge) 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 a free quote Prices page, loads on click; a preview of the calendar until connected Cal.com
Install deposits, tune-ups and spring repairs Prices page (one-time prices) Stripe or Lemon Squeezy
Door 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
Quote 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 tells anyone to adjust a spring or cable themselves, and tells anyone with a broken spring or a door off its track to leave it closed and call 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 door panel), Services (cards whose doors roll up as they scroll in), How a door goes in (a garage opening drawn from inside, built stage by stage), Projects (with their door sheets), Numbers (on cycle counters whose wheels roll up to each figure), The area on a map, Guides, Door care notes by email and Closing call (a ribbed petrol band with a line of light along its top and a photo in a sodium-yellow frame). With reduced motion nothing moves.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (porch amber, the warm light of a garage at night: buttons, links, marked words and their light by day), the second (midnight petrol: the deep bands, the plates, dark fills and the night theme) and the third (sodium yellow: chips, the status line, light fills and the light in the drawings). The accent and the petrol are darkened until white text on them is readable and the yellow 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 (coved, or square). Coved corners use CSS corner-shape: scoop; browsers that don’t have it yet show rounded corners. The site opens on the pale concrete day theme even when the visitor’s system is dark; the toggle switches to the drive after dark, and the browser remembers the choice. The header strip, the tab bar and the deep bands look the same in both.

Hinge is ready for more languages: see Languages.

A small game, Black ice: a winter driveway from above, glazed with ice, the garage door open at the top. A car on ice can’t stop where it likes: pushed up, down, left or right, it slides until it meets a snowbank, a bin, another car, the house or the edge of the drive. Get the amber car to stop inside the garage, and the door comes down behind it. From the second drive on it can’t get there alone: slide one of the other cars first to make a stop where there isn’t one. Tap a car, then tap where it should go (or swipe it), or pick a car with keys 1–3 and push it with the arrow keys, or use the buttons; dots show where the picked car would stop each way. U undoes and R starts over. Each drive scores 100 × the fewest moves ÷ yours; the fewest is worked out exactly by a search over every position of every car. Three drives: 6 × 6 with the amber car alone, 7 × 7 with one more car and 8 × 8 with two. 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 HomeAndConstructionBusiness with the areas it serves and its packages (price ranges as a minimum and a maximum), services as Services with their price, projects as CreativeWorks, a door going in step by step 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).