Skip to content

Whisker

Whisker is a site for a cat shelter or rescue: shelters, foster networks, cat cafés with adoptions, TNR groups, municipal shelters and sanctuaries. It is set edge to edge in a sunlit room: a wall with a soft wallpaper and sunbeams that sweep across it as you scroll, cardboard boxes, shipping labels and packing tape. On the home page a row of boxes stands on the floor; the first is open with a cat peeking out, and as you scroll the row slides along and each box opens in turn. The demo is a fictional rescue, Nine Lives Cat Rescue.

Whisker 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)
Cats, adopt (steps, fee, questions), help (ways, donations, wishlist), happy tails, visit (opening hours), 404 Pages → the page’s own entry
Cats (age, coat, home, gets on with, traits, care line, story, photo, status, sponsorship) Content → Cats
Happy tails Content → Happy tails
Name, charity details, address, navigation, header button, profiles, packing tape words Pages → Site settings
Buttons, labels, filters, chat, emails, game texts Content → Interface texts
Privacy, terms Pages → Legal

In headlines, words wrapped in *stars* get a strip of packing tape stuck underneath as they scroll into view, as in “Every box has *a cat in it*”.

Each cat is an entry with its age (as you’d say it, “about 13”) and age group, coat, the home it needs (indoor only, a garden, or either), when it arrived, whether it gets on with children, other cats and dogs (yes, no or ask us), a few traits, a short summary, a “handle with care” line for its shipping label and its story. The status is looking for a home, reserved or adopted; only cats looking for a home are in the boxes on the home page, and adopted ones stay on the cats page, marked, until you remove them. The cats page filters by age, the home you can offer and who they get on with, with no JavaScript.

The photo is a cut-out of the cat peeking over an edge: a PNG with a transparent background, head and front paws in frame, the bottom cut straight just below the paws (4:3 works best). Remove the background with any tool (most phones’ photo apps do it) and export a PNG; it is served as AVIF or WebP with its transparency. The box draws the rim, so the paws rest on it.

Everything works without keys; each feature switches on with its variables in .env.example.

Feature Where Service
Donate once, sponsor a cat monthly Help page (one-time Price ids), each cat’s page (a monthly Price id) Stripe
Book a visit to meet a cat Adopt page, loads on click; a preview of the calendar until connected Cal.com
Newsletter, fosters and volunteers Home, happy tails and help pages, with a welcome email Supabase
Contact form Visit page; messages go to the email in Site settings Resend
AI chat On every page, answers about the cats, adopting, helping and visiting; never promises a cat Claude
Search ⌘K or the search button: cats, happy tails, adopt, help, visit built in, or Algolia
Analytics Every page; Google Analytics only after consent Plausible, Umami, Google Analytics

The home page is built from these sections, in any order: Who’s in the box? (the row of boxes), Cats looking for a home (their boxes on shelves, each opening as it scrolls into view), How adoption works (the steps tracked like a parcel, a little box travelling the route), Ways to help (stickers pressed onto the side of a big box), Numbers (rubber stamps), Happy tails (photos taped to the wall), Newsletter sign-up and Closing call. Bands of packing tape run across the page between some of them, printed with the words in Site settings → Packing tape. With reduced motion, the boxes stand open side by side and nothing moves.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent (ginger: buttons and marks), the second (plum) and the third (sage), used for fills. Cardboard, packing tape and the inside of the boxes are materials, the same whatever your colors. Buttons are darkened until their white text is readable, the second and third are lightened until ink text on them is; a color that can’t get there stops the build with a message. Brand also sets the fonts (text, headings, and the typewriter face for labels and tape) and the corners. The site opens in the day theme even when the visitor’s system is dark; the toggle switches to the night room, a dim blue lit by a lamp, and the browser remembers the choice.

Whisker is ready for more languages: see Languages.

A small game, Tiptoe: get across the room to the treat jar without waking the cat asleep on the rug. Take a step with the button, a tap or the space bar, at tiptoeing pace; when the cat’s tail twitches an eye is about to open, and a step while it’s open wakes her. Five rooms, the cat sleeping lighter in each; 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, cats and happy tails for AI assistants, in every language.
  • Pages carry JSON-LD: the rescue as an AnimalShelter, the cats as an ItemList, adopting as a HowTo, questions as a FAQPage, and each happy tail as a BlogPosting.
Terminal window
pnpm dev # local site, editor at /keystatic
pnpm build # production build
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).