Skip to content

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.

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 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 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”.

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.

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 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.

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

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.

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.

Lacquer is ready for more languages: see Languages.

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.

  • AGENTS.md describes the project and its design rules for coding assistants (Claude Code reads it through CLAUDE.md, Cursor through .cursor/rules/).
  • /llms.txt lists your pages, services, sets, artists and guides for AI assistants, in every language.
  • Pages carry JSON-LD: the studio as a NailSalon with its opening hours and offers, services as Services with their price, sets as CreativeWorks, artists as Persons, questions as a FAQPage, and each guide as a BlogPosting.
Terminal window
npm run dev # local site, editor at /keystatic
npm run build # production build
npm run map -- fetch # draw the map round map.config.json from OpenStreetMap
npm 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).