An MVP appointment booking system for a single Singapore small business, built with Next.js App Router, TypeScript, Tailwind CSS, and Supabase.
- Public booking flow at
/book - Guest booking with service, date, slot, name, phone, and notes
- Availability generated from seeded business hours
- Admin auth with Supabase email/password
- Admin dashboard with grouped appointments and status actions
- Supabase SQL schema, seed data, and setup instructions
- Mobile-friendly UI for both customers and owners
- Next.js 16 App Router
- TypeScript
- Tailwind CSS v4
- Supabase Postgres + Auth
- Vercel-friendly deployment
app/
(public)/
page.tsx
book/page.tsx
(admin)/
admin/page.tsx
admin/login/page.tsx
api/availability/route.ts
components/
admin/
booking/
site/
ui/
lib/
actions/
supabase/
availability.ts
queries.ts
validations.ts
supabase/
schema.sql
seed.sql
types/
app.ts
database.ts
Copy .env.example to .env.local and fill in:
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
SUPABASE_DB_URL=The anon key is safe for browser auth. The service-role key is server-only and powers server-side booking reads/writes plus admin data access. SUPABASE_DB_URL is optional and only useful if you want direct SQL access from your own environment.
- Create a new Supabase project.
- In the Supabase SQL editor, run
supabase/schema.sql. - Run
supabase/seed.sql. - In Supabase Auth, create the admin user manually:
- Example email:
[email protected] - Example password: any strong password you choose
- Example email:
- Copy the new user's UUID from the Auth users table.
- Run the commented SQL snippet at the bottom of
supabase/seed.sqlwith that UUID to insert theadmin_userslink row. - Add the project URL, anon key, and service-role key to
.env.local.
npm install
npm run devOpen http://localhost:3000.
npm run lint
npm run typecheck
npm run test
npm run build/is a lightweight marketing/demo homepage./bookloads the business and services from Supabase.- Slot availability is fetched from
/api/availability. - Booking submission uses a server action:
- validate input with Zod
- upsert customer by phone
- create a pending appointment
/admin/loginuses Supabase email/password auth./adminis protected by proxy auth middleware.- Dashboard data is loaded server-side and grouped into:
- today’s appointments
- pending bookings
- confirmed bookings
- cancelled bookings
- Owners can confirm, cancel, or complete bookings from the dashboard.
Seed data includes:
- 1 business:
Lion City Barber - 3 services
- Tue-Sun operating hours, Monday closed
- sample customers
- sample appointments across pending, confirmed, cancelled, and completed
- Push this repo to GitHub.
- Import the project into Vercel.
- Add the same environment variables in Vercel project settings.
- Deploy.
- Ensure your Supabase URL is added to Auth redirect settings if you later expand auth flows beyond password sign-in.
- This MVP is single-business only.
- Payments, WhatsApp, AI chat, analytics, and multi-branch support are intentionally out of scope.
- The UI still renders in preview mode without env vars, but live booking and admin features require Supabase to be configured.
- Customer booking edits and cancellations via secure links
- Business-hours editing in the admin dashboard
- Appointment reminders by SMS or WhatsApp
- Staff assignment and multi-calendar views
- Basic reporting for utilization and no-shows