# Booking Kit · Cadence

> An appointment-booking app for iOS, Android and web with live slots, payments and reminders.

The OTF **Booking Kit (Cadence)** is a two-sided booking app for coaches, therapists, stylists and
consultants. Clients find a provider, pick a service, see live availability, book and pay.
Providers manage their schedule, weekly hours and time off. One codebase ships iOS, Android and
web. Run it live on [its kit page](/templates/booking-kit#run-it-live) or at
[booking-preview.otf-kit.dev](https://booking-preview.otf-kit.dev).

## Stack

| Layer       | Choice                                                                    |
| ----------- | ------------------------------------------------------------------------- |
| Framework   | Expo SDK 54 + React 19 + Expo Router 6 (iOS · Android · Web)              |
| Data        | supabase-js with row-level security; TanStack Query                       |
| Realtime    | Supabase Realtime on `bookings`, so open slots update live                |
| Server      | Hono 4 + Bun, only for privileged work (checkout, webhook, reminders)     |
| Database    | Supabase Postgres, with a database rule that blocks double bookings       |
| Auth        | Supabase Auth: email, Google and a demo login                             |
| Payments    | Stripe Checkout per booking                                               |
| Email       | Resend reminders built with `@react-email/components`                     |
| Deploy      | Railway (web + API) and EAS Build (native)                                |

## Pre-built screens

The kit ships with **9 screens**:

- **Auth**: login and signup
- **Discover**: providers and services
- **Provider profile**: services and cover
- **Book**: month calendar and slot picker
- **Booking confirmed**
- **My bookings**
- **Provider schedule**: agenda, weekly availability and time off
- **Profile**

## Conventions

- **Client first**: reads and writes go straight to Supabase, scoped by row-level security. The
  server only runs what needs the service-role key.
- **Availability**: the `available_slots()` function returns open slots; the database rejects an
  overlapping booking, so two clients can never take the same slot.
- **Blocks**: `<ProviderCard />`, `<ServiceCard />`, `<MonthCalendar />`, `<SlotGrid />`,
  `<BookingCard />` and `<AgendaRow />`.

## Adding things

The kit's `ai/prompts/` folder has 20 task prompts: add a service, edit availability, add a field
to bookings, change the theme, add Google sign-in or SMS reminders, and more. `CLAUDE.md`,
`AGENTS.md` and `.cursorrules` give your editor the same context.

## Deploy

Create a Supabase project (local with Docker, or hosted), copy `.env.example` to `.env`, run
`bun run supabase:reset` to apply migrations and seed data, then `bun dev`. Railway deploys the
web export and the API from one `Dockerfile` against a hosted Supabase project; native apps ship
through EAS Build. The deployment guide ships with the kit.

## Required env

| Variable                          | Purpose                                      |
| --------------------------------- | -------------------------------------------- |
| `EXPO_PUBLIC_SUPABASE_URL`        | Supabase project URL (client)                |
| `EXPO_PUBLIC_SUPABASE_ANON_KEY`   | Public anon key (client, RLS-scoped)         |
| `SUPABASE_URL`                    | Supabase project URL (server)                |
| `SUPABASE_SERVICE_ROLE_KEY`       | Server-only key for checkout and reminders   |

Stripe and Resend variables are optional; `.env.example` lists them.

## Buy

<DocsBundleBuyButton source="docs_kit_page" />

[$99 on otf-kit.dev](https://otf-kit.dev/templates/booking-kit) — or get the
[Everything Bundle](/docs/templates/starter-bundle) ($149 = 5 live kits + all 15 landing templates; $630 separately, save $481.)
