Mobile-first booking portal for SUP rentals with Stripe Checkout, an admin dashboard, and PostgreSQL support for production hosting.
- Public booking form with 15-minute time slots from 8:00 to 22:00
- Server-side booking validation and price calculation
- Stripe Checkout payment flow
- Automatic Stripe payment confirmation through webhooks and admin sync
- Admin dashboard with booking groups, notes, payment status, and revenue stats
- Local JSON storage for development
- PostgreSQL storage when
DATABASE_URLis configured
- 90 min.: 15,00 EUR per board
- 2h: 20,00 EUR per board
- 3h: 30,00 EUR per board
- 1/2 day: 40,00 EUR per board
- Day ticket: 50,00 EUR per board
- 2-person surcharge: 5,00 EUR per board
Board categories: lightweight up to ca. 65 kg, allround women up to ca. 80 kg, super-allround up to ca. 120 kg, bigboards up to ca. 180 kg. Super-allround boards can be booked for 2 people; bigboards are for 2 adults only.
npm install
cp .env.example .env
npm startOpen http://localhost:3000.
For development with auto-reload:
npm run devCreate .env from .env.example and set at least:
ADMIN_PASSWORD=dein_sicheres_passwort
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
PUBLIC_BASE_URL=http://localhost:3000Optional:
PORT=3000DATABASE_URL=postgres://...NODE_ENV=productionPUBLIC_BASE_URL=https://deine-domain.example
In production, ADMIN_PASSWORD must be configured or admin login is disabled.
Local development uses bookings.json, which is ignored by git and created automatically.
Production uses PostgreSQL when DATABASE_URL is present. To migrate local JSON bookings into PostgreSQL:
npm run migratenpm testRailway and Render are both supported. See HOSTING_GUIDE.md and RAILWAY_SETUP.md for deployment steps.
Minimum production variables:
ADMIN_PASSWORDSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETPUBLIC_BASE_URLDATABASE_URLNODE_ENV=production
ISC