A booking service for escape rooms running on Cloudflare Pages + Functions with D1 database, Resend for emails, and Turnstile for CAPTCHA.
npm install -g wrangler
wrangler logincd escape-room-booking
npm installwrangler d1 create escape-rooms-dbCopy the database_id from the output into wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "escape-rooms-db"
database_id = "paste-your-id-here"onboarding@resend.dev for testing)localhost for dev)YOUR_TURNSTILE_SITE_KEY in public/book.html with your Site KeyTest keys (always passes):
1x00000000000000000000AA1x0000000000000000000000000000000AAecho -n "your-password" | shasum -a 256 | cut -d' ' -f1Create .dev.vars for local development:
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD_HASH=your-sha256-hash
RESEND_API_KEY=re_xxxxxxxxxxxxx
FROM_EMAIL=bookings@yourdomain.com
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA# Local
npm run db:init:local
# Production (after deploy)
npm run db:initnpm run devnpm run deployThen set secrets:
wrangler secret put ADMIN_EMAIL
wrangler secret put ADMIN_PASSWORD_HASH
wrangler secret put RESEND_API_KEY
wrangler secret put FROM_EMAIL
wrangler secret put TURNSTILE_SECRET_KEYpublicDB to your databaseAfter deploy, initialize the production database:
npm run db:initescape-room-booking/
├── public/
│ ├── index.html # Landing page
│ ├── book.html # Booking form
│ ├── styles.css
│ └── admin/
│ └── index.html # Admin dashboard
├── functions/
│ └── api/
│ ├── rooms.js
│ ├── bookings.js
│ ├── bookings/
│ │ └── slots.js
│ └── admin/
│ ├── _middleware.js
│ ├── login.js
│ ├── bookings.js
│ ├── bookings/[id]/cancel.js
│ ├── rooms.js
│ └── rooms/[id].js
├── schema.sql
├── wrangler.toml
└── package.json| Method | Endpoint | Description |
|---|---|---|
| GET | /api/rooms | List visible rooms |
| GET | /api/bookings/slots?room_id=X&date=YYYY-MM-DD | Get booked time slots |
| POST | /api/bookings | Create booking |
Authorization: Bearer <token>)| Method | Endpoint | Description |
|---|---|---|
| POST | /api/admin/login | Get auth token |
| GET | /api/admin/bookings?filter=today|upcoming|past | List bookings |
| POST | /api/admin/bookings/:id/cancel | Cancel booking |
| GET | /api/admin/rooms | List all rooms |
| POST | /api/admin/rooms | Create room |
| PATCH | /api/admin/rooms/:id | Update room visibility |
| DELETE | /api/admin/rooms/:id | Delete room (fails if bookings exist) |
| Variable | Description |
|---|---|
ADMIN_EMAIL | Admin login email |
ADMIN_PASSWORD_HASH | SHA-256 hash of admin password |
RESEND_API_KEY | Resend API key |
FROM_EMAIL | Sender email for notifications |
TURNSTILE_SECRET_KEY | Cloudflare Turnstile secret |
public/index.html (location, hours, contact)generateTimeSlots() in public/book.htmlpublic/styles.css