Lacquer
Lacquer is a site for a nail studio: manicures, gel, BIAB, hand-painted nail art, pedicures and repairs. It also fits nail bars, independent nail artists, mobile manicurists and lash and brow studios. It is set in a fantasy world made of lacquer: the home page opens on a short film of lilac dunes with a river of cherry polish, bubble planets and drifting petals, with a giant headline across the bottom. The page behind everything is a pearly lilac sky with slow iridescent light. The demo is a fictional studio, Petal & Polish, in Savannah, Georgia.
Lacquer 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, gallery, artists, journal, 404 | Pages → the page’s own entry |
| Prices (the menu’s texts and add-ons, booking, gift cards and the deposit, questions) | Pages → Prices page |
| Visit (opening hours, details, map, contact form, questions) | Pages → Visit page |
| Services (category, price, time, how long it lasts, bottle color, lovely for, what happens, aftercare, questions, photo) | Content → Services |
| Gallery sets (service, artist, shape, shades, time in the chair, story, photo) | Content → Gallery |
| Artists (role, loves doing, experience, languages, services, portrait, biography) | Content → Artists |
| Journal (guides; one can be for members only) | Content → Journal |
| Name, phone, address, currency, navigation, header button, 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 the lacquer color, as in “Fresh from *the
chair*”. The opening’s headline has its two lines in separate fields.
The film in the opening
Section titled “The film in the opening”The opening plays a short muted film across the whole window (Pages → Home page → Opening → Film, a
file in public/, e.g. /media/hero.mp4), with its first frame as the photo. The photo shows at once;
the film is fetched after the page has loaded and fades in when it plays, so the page stays fast. With
reduced motion or a data saver the photo stays. Keep the lower part of the picture calm: the headline
sits there on a veil of violet dusk.
To make your own: film a slow, dreamy shot (or generate one), 10 to 20 seconds, then export it about 1280 pixels wide as H.264 MP4 without sound, ideally under 2 MB. A clip that ends where it begins loops without a cut. Replace the photo with its first frame.
The shelf, Design your set and the menu
Section titled “The shelf, Design your set and the menu”- The shelf shows every service as a bottle filled with the service’s own color (Content → Services → Bottle color). Point at a bottle and it tips toward you.
- Design your set (Pages → Home page) lets visitors pick a nail shape (round, square, almond, coffin, stiletto) and one of up to ten shades, and shows them on five nails. It works without JavaScript.
- The menu (home and prices pages) is a small calculator: pick a service and tick add-ons, and the total of the visit adds itself up. Services come from Content → Services in their categories; add-ons live on the prices page. Prices are whole numbers, written without the currency (Site settings → Currency adds it), with an optional note like “from” or “per nail”.
The gallery
Section titled “The gallery”Each set has a page with its photo, the shades used (name and color), the shape, the time in the chair, the service, the artist who made it and its story. The gallery page is a masonry of sets with a filter by shape; a service’s page and an artist’s page show the sets made with it.
Booking and payments
Section titled “Booking and payments”The prices page holds booking with Cal.com, gift cards and the nail art deposit. Each payment option takes a one-time Stripe Price id (or a Lemon Squeezy variant). Without keys, the booking shows a preview of the calendar and the payment buttons explain how to switch them on.
The map
Section titled “The map”The visit page shows the streets round the studio, 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 the studio’s coordinates in map.config.json and run npm run 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 visit | Prices page, loads on click; a preview of the calendar until connected | Cal.com |
| Gift cards and the nail art deposit | Prices page (one-time prices) | Stripe or Lemon Squeezy |
| Newsletter | Home and journal pages, with a welcome email | Supabase or Mailchimp |
| Contact form | Visit page; messages go to the email in Site settings | Resend |
| AI chat | Every page; answers about services, prices, the gallery and visiting, never gives medical advice | Claude or OpenAI |
| Members-only guide | A journal post marked “Members only” | Clerk |
| Search | ⌘K or the search button: services, sets, artists, guides, prices, visit | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics, PostHog |
| Photos | Served by Cloudinary when it is set | Cloudinary |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Opening (the film, the headline and the buttons), The shelf, Design your set, The menu, Gallery, Artists, Reviews (each on a card topped with the shade the client wore), Questions, Journal, Newsletter and Closing call. With reduced motion everything stands still.
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent
(cherry lacquer: the button, links, marked words), the second (lilac: the page’s tint and soft
fills) and the third (peach: the glow and highlights). A deep violet for the footer and the closing
call is derived from them. Buttons are deepened until their pearl text is readable and links are
adjusted until they read on the page; a color that can’t get there stops the build with a message.
Brand also sets the corners and two fonts: one for headings (Bricolage Grotesque, Syne, Fraunces, DM
Serif Display or Unbounded) and one for text (DM Sans, Figtree, Manrope or Outfit). The site opens in
its day theme; the toggle switches to the night (a violet dusk), and the browser remembers the choice.
Languages
Section titled “Languages”Lacquer is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Shade order: a tray of polish swatches blends between four fixed corner shades and gets shuffled. Tap two swatches (or move with the arrow keys and press Enter) to swap them until the gradient flows again. Five palettes, the trays grow; the fewest swaps is kept as the best score in the visitor’s browser.
AI assistants and search engines
Section titled “AI assistants and search engines”AGENTS.mddescribes the project and its design rules for coding assistants (Claude Code reads it throughCLAUDE.md, Cursor through.cursor/rules/)./llms.txtlists your pages, services, sets, artists and guides for AI assistants, in every language.- Pages carry JSON-LD: the studio as a
NailSalonwith its opening hours and offers, services asServices with their price, sets asCreativeWorks, artists asPersons, questions as aFAQPage, and each guide as aBlogPosting.
Commands
Section titled “Commands”npm run dev # local site, editor at /keystaticnpm run build # production buildnpm run map -- fetch # draw the map round map.config.json from OpenStreetMapnpm run cms -- sanity schema # 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).
