A production marketplace where players discover venues, see live availability, reserve an individual spot or an entire turf, split the cost, and pay securely. Venue partners get a self-service dashboard for inventory, pricing, bookings, analytics, and payouts.
Interface
The booking engine
Booking is not a calendar form. Availability, capacity, pricing, payment, and abandoned checkouts all have to agree on the same time window. Good Bookies keeps that flow server-authoritative from the first tap to the confirmed slot.
-
01
Choose a window
Two taps define a start and an exclusive end time. Every slot is stored as minutes from midnight, supporting both 30- and 60-minute venues.
-
02
Resolve the price
Date override, day rule, peak surcharge, duration discount, coupon, and individual-vs-full-turf split resolve in one shared pricing engine.
-
03
Hold inventory
A pending booking locks the window for 15 minutes. Stale holds expire whenever availability is read, so abandoned checkout never blocks play.
-
04
Verify payment
Razorpay creates the order, but only a server-side signature check confirms the booking. Dismissal or failure releases the hold explicitly.
Architecture
-
DB
Split storage by responsibility
Postgres owns relational and transactional truth. Two MySQL stores isolate user avatars from venue photo/video blobs, avoiding bloated Postgres backups and expensive media egress.
-
API
One media boundary
/api/media/:scope/:idselects the correct database, streams bytes with MIME and cache headers, and keeps storage details invisible to every image and video component. -
SSR
SSR without serverless lock-in
A hardened custom Node server runs TanStack Start on commodity hosting, serves static assets and API routes, and boots from a verified committed production build.
Engineering decisions
-
₹
One source of price truth
Preview and checkout call the same pricing engine, eliminating the class of bugs where the number shown in the UI differs from the amount charged by Razorpay.
-
↻
Inventory heals itself
Reading a schedule first expires stale pending bookings and their payments. Availability therefore recovers even if a browser closes midway through checkout.
-
%
Refund rules are code, not copy
Cancellation tiers compute exact paise values: full refund at 24+ hours, half at 12–24 hours, none below 12 hours, less the defined convenience fee.
-
@
Phone identity claimed after confirmation
Profiles do not claim a unique phone number until email confirmation, preventing failed sign-ups from permanently locking a player's number.
-
+
Open spots become community inventory
Partial bookings can open a lobby and optionally publish remaining capacity through a community webhook, helping players fill a match.
Stack
-
UI
Application
- TanStack Start
- React 19
- TypeScript 5.8
- Tailwind CSS 4
- shadcn/ui
- Framer Motion
-
RPC
Server & data
- TanStack Query
- createServerFn
- Zod
- Supabase
- PostgreSQL
- MySQL
-
₹
Commerce & identity
- Razorpay
- Supabase Auth
- Row Level Security
- Role-based access
-
CI
Build & hosting
- Vite 7
- Node.js
- GitHub Actions
- Hostinger
- SSR
Good Bookies / Live product