Toon
Toon is a brand story site drawn like a cartoon: thick outlines, flat colors, halftone dots, speech bubbles and a mascot who narrates. The home page tells your story chapter by chapter as visitors scroll; then come a shop with product pages, your story, a journal and a visit page. Headlines pop in word by word, buttons bounce and squish, a little honey jar fills as you read, and pages close and open on a circle like the end of an old cartoon.
Toon 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) |
| Shop, story, journal, visit, 404 | Pages → the page’s own entry |
| Products | Content → Products |
| Journal posts | Content → Journal |
| Brand name, mascot name, email, location, navigation, header button, profiles | Pages → Site settings |
| Buttons, labels, chat, search, emails, game texts | Content → Interface texts |
| Privacy, terms | Pages → Legal |
Products marked Featured come first, then by Order. Each product has a price as shown, a size, tasting notes, an optional sticker (Badge), a color for its card and an image. Journal posts pick a color too.
In headlines, a word wrapped in *stars* sits on a wobbly color blob, as in
“Honey with a *story* in every jar”.
The story
Section titled “The story”The Story section on the home page is a list of chapters (two to eight). Each chapter has a scene (an illustration, 4:3), a title, a few sentences, a speech bubble for the mascot and a color. While a chapter’s text scrolls by, its scene stays on screen; in browsers with scroll-driven animations the scene pops in with a squash and stretch, the mascot flies in and the text card swings into place. Other browsers, and visitors who prefer reduced motion, get the same layout without the movement. It needs no JavaScript.
The mascot
Section titled “The mascot”The mascot (a bee in the demo) is drawn in your brand colors, so it matches any palette. Name
it in Site settings: the chat answers as the mascot, and what it says in speech bubbles comes
from the content. To use your own character, replace the drawing in
src/components/Mascot.astro.
The map
Section titled “The map”The visit page shows an illustrated map (Pages → Visit page → Map) with a pin you place in percent from the left and top, its label and your address. Add your latitude and longitude and the page also offers directions (Google Maps, in a new tab) and a live OpenStreetMap, which loads only when the visitor opens it, so nothing is requested from a third party before that. Without coordinates it says how to add them.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Shop | Product pages: a Buy button per product with a Stripe Price id (one-time) | Stripe |
| Contact form | Visit page; messages go to the email in Site settings | Resend |
| Book a visit | Visit page, loads on click | Cal.com |
| Newsletter | Home and journal pages, with a welcome email | Supabase |
| Ask the mascot | Chat on every page, answers from your products, shop questions, story and journal | Claude |
| Search | ⌘K or the search button: products, journal, shop, story, visit | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics |
After a payment, the Stripe webhook (/api/stripe/webhook) emails the buyer; add your own steps
there, such as telling your shipping tool.
Sections
Section titled “Sections”The home page is built from these sections, in any order: Hero (an opening scene with the mascot), Story (scrolling chapters), Products, Ribbon (words floating by on a band), Numbers, Latest journal posts, Newsletter sign-up and Closing call to action.
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds four fills: the
accent (buttons, highlights, the blobs behind words) and a second, third and
fourth color for cards, stickers, bubbles and chapters; the third also tints the daytime
sky and the fourth colors the hills in the footer. Text on a fill is always ink, so each fill
is lightened until it is readable; a color that can’t get there stops the build with a message.
The ground, sky, links and the night theme (a starry indigo sky) are derived from the fills.
Brand also sets the fonts (text, headings, labels) and the outline weight (thin or bold).
Languages
Section titled “Languages”Toon is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Honey run: honey drops and raindrops fall from the sky; move the jar to catch the honey and dodge the rain (drag, arrow keys or A/D, or the Left and Right buttons). A raindrop in the jar or honey on the grass costs a heart; after three the game ends. The best score is kept in the visitor’s browser.
AI assistants and search engines
Section titled “AI assistants and search engines”AGENTS.mddescribes the project for coding assistants (Claude Code reads it throughCLAUDE.md, Cursor through.cursor/rules/), including what makes the look./llms.txtlists your pages, products and journal posts for AI assistants, in every language.- Pages carry JSON-LD: the brand, each product with its price, the shop’s questions and each post.
Commands
Section titled “Commands”pnpm dev # local site, editor at /keystaticpnpm build # production buildpnpm 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).