Poise
Poise is a site for a Pilates studio: reformer, mat and tower classes, prenatal Pilates and private sessions. It also fits barre and yoga studios, independent instructors and boutique fitness studios. It is clean and calm: one typeface, flat colors, a fine line grid behind the page, and lots of light. The home page opens like a commercial, on a short film of the studio across the whole window with the headline over its calm side. The demo is a fictional studio, Kestrel Pilates, in Asheville, North Carolina.
Poise follows two open design skills, landing-page-design and design-to-motion (ai-design-skills by Elaya, MIT): one typeface and no italics, Tailwind’s type and spacing scales, flat backgrounds, a single easing curve, a word by word tagline, cards whose pictures act out what they do, and copy written without filler.
Poise 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) |
| Classes, instructors, journal, 404 | Pages → the page’s own entry |
| Schedule (the week, day names, a note) | Pages → Schedule page |
| Pricing (first class, memberships, class packs, booking, questions) | Pages → Pricing page |
| Visit (opening hours, details, map, contact form, questions) | Pages → Visit page |
| Classes (level, length, size, equipment, price, good for, what happens, what to bring, questions, photo) | Content → Classes |
| Instructors (role, teaches best, certification, experience, languages, classes, portrait, biography) | Content → Instructors |
| Journal (guides; one can be for members only) | Content → Journal |
| Name, phone, address, navigation, header button, profiles | Pages → Site settings |
| Buttons, labels, chat, emails, game texts | Content → Interface texts |
| Privacy, terms, cancellation policy | Pages → Legal |
In headlines, words wrapped in *stars* are set in the accent color, as in “Five ways to *move
well*”. 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 left side of the picture calm: the headline
sits there. On phones the copy sits above the film.
To make your own: film a slow, steady shot of your studio (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 card on the right of the opening shows the next class with spots from your schedule and acts out a booking; the numbers along the bottom are in the same section.
The schedule
Section titled “The schedule”Pages → Schedule page holds each day’s classes: the time (24-hour, shown as “7:15 am”), the class and the instructor (by their file names) and the spots left (0 shows “Waitlist”). The schedule page lists the week with filters by class and time of day (they work without JavaScript); the home page shows today, or the next day with classes; each class page lists its own times; the chat knows them too.
Pricing, booking and payments
Section titled “Pricing, booking and payments”The pricing page holds the free first class, up to four monthly memberships (mark one as the most popular), up to four class packs, the small print, booking with Cal.com and questions. Memberships take a monthly Stripe Price id (or a Lemon Squeezy subscription variant), packs a one-time one. 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 class | Pricing page, loads on click; a preview of the calendar until connected | Cal.com |
| Memberships and class packs | Pricing page and home page (monthly and 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 classes, the schedule, prices 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: classes, instructors, guides, schedule, pricing, 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 copy, the numbers and the booking card), Tagline (large words that light up one by one as you scroll), Benefits (four cards with live pictures: the schedule finds an open spot, a class pack is used and refills, a line of classes per week is read, the waitlist moves up), How it works (three steps with photos), Classes, Schedule preview, Instructors, Reviews, Pricing, Questions, Journal, Newsletter and Closing call (the same button as the opening). 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
(clay: the button, links, marked words), the second (sand: soft fills) and the third (deep green:
the footer, the popular membership, the opening hours). Buttons are deepened until their white 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 the one typeface (Geist, Manrope or Poppins).
The site opens in its day theme whatever the visitor’s system prefers; the toggle switches to the night
(neutral dark greys), and the browser remembers the choice.
Languages
Section titled “Languages”Poise is ready for more languages: see Languages. Times are written as
“7:15 am”; for a 24-hour clock change clock() in src/lib/collections.ts.
The 404 page
Section titled “The 404 page”A small game, Set the springs: each client on the reformer needs an exact resistance. Switch the springs (red 20 lb, blue 15, yellow 10, green 5) on and off with a click, a tap or keys 1 to 5 until the load matches, before the time runs out; each client has a second less. Eight clients; 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 and its design rules for coding assistants (Claude Code reads it throughCLAUDE.md, Cursor through.cursor/rules/)./llms.txtlists your pages, classes, the week’s schedule, instructors and guides for AI assistants, in every language.- Pages carry JSON-LD: the studio as an
ExerciseGymwith its opening hours, classes asCourses with their weekly times, the schedule asEventSeries, memberships and packs as offers, instructors 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).
