SP Calendar
Self-hosted appointment booking: a public booking site and a private admin area. Production: https://calendar.spboucher.ai · French (Québec) first, English available.
- Visitors pick a real free slot, see it in their own time zone, and submit a request; the owner approves, declines or proposes another time. A pending request is never shown as a confirmed appointment.
- The owner manages weekly hours, exceptions, private events, appointment types, contacts and settings, and signs in with a passkey (Touch ID / Face ID / security key).
- No double booking: per-owner lock, re-check at approval, and a PostgreSQL exclusion constraint.
- Nothing is simulated: every control calls the API; what is not configured says so.
Stack
Next.js 16 · React 19 · TypeScript · Tailwind 4 · PostgreSQL 17 · tsx worker · @simplewebauthn · Zod ·
Vitest · Playwright. No Redis (PostgreSQL outbox). Deployed with mld under PM2.
Local development
bash
pnpm install
createdb sp_calendar_dev && createdb sp_calendar_test && createdb sp_calendar_e2e
cp .env.example .env # DATABASE_URL, APP_URL=http://localhost:8660, APP_SECRET, OWNER_EMAIL, OWNER_NAME
pnpm migrate && node_modules/.bin/tsx scripts/bootstrap.ts # prints the one-time passkey enrolment link
pnpm build && pnpm start # http://localhost:8660 (worker: pnpm worker)pnpm dev works for interface work; the end-to-end suite always runs against a production build.
Checks
bash
pnpm typecheck && pnpm lint && pnpm test && scripts/e2e.sh && pnpm secrets:scanDocumentation
| File | Content |
|---|---|
| docs/ARCHITECTURE.md | audit, components, availability engine, states, data model |
| docs/PLAN.md | phases, validation record, acceptance tests, status table |
| docs/DECISIONS.md | decision log |
| docs/SECURITY.md | authentication, authorisation, privacy (Law 25), known limits |
| docs/OPERATIONS.md | deployment, first sign-in, recovery, e-mail, backups, troubleshooting |
Routes
| Path | Purpose |
|---|---|
/ |
public profile and appointment types |
/book/[slug] |
booking flow |
/manage/[token] |
visitor's management link |
/privacy |
privacy policy |
/admin … |
dashboard, requests, agenda, availability, types, contacts, settings |
/api/v1/public/*, /api/v1/auth/*, /api/v1/admin/*, /api/health |
API |