Case study · № 032025Hackathon build

QuickCourt

A full-stack sports-court booking platform where players discover venues, check real-time slot availability, and pay online, while facility owners manage courts and admins approve venues. Built by a small team in a two-day sprint.

Team~3 people
My roleBackend / schema
PaymentsRazorpay
AuthJWT + OTP
quickcourt · booking model
ClientAPIModulesDataReactVite · React QueryExpress/api/*JWT + OTPemail verifyVenues / Courtsowner-managedSlotsavailability engineBookingslifecyclePostgreSQLPrismaRazorpaycheckoutCloudinarygalleriespayimages
Fig. 1 · Court-booking platform — per-slot availability keyed by court/date/time over Prisma·Postgres, Razorpay checkout, OTP-verified auth. (I built the backend & schema.)
01

Context

Booking a local court — badminton, turf, tennis — is still mostly phone calls and guesswork: no visibility into open slots, no online payment, no single place to look. QuickCourt centralises venue discovery, per-hour court availability, online payment, and the owner/admin operations behind them.

A small team, a two-day build. I owned the backend foundation.

venues · courts
02

My role, honestly

I was the one who set the project up and gave it a spine. My commits are the founding ones: the Express server, the Prisma data model, the route skeleton across auth, venues, courts, bookings, slots, payments, and reviews, the JWT auth middleware, and the email utilities. Teammates then built the feature surface — the dashboards, the payment integration UI, the venue search — on top of that structure. I’m the repo owner, but the honest framing is architecture-and-scaffold, not the whole product.

slots · bookings
03

The booking model

The core of the schema is availability. Time slots are keyed uniquely per court, date, and time, each carrying isBooked and isBlocked flags, so the availability engine is a lookup rather than a computation and double-booking is prevented by the key itself.

A booking moves through a lifecycle — pending, confirmed, completed, cancelled — carrying its Razorpay order and payment IDs, and registration is gated by email-OTP verification before anyone can hold a slot.

04

Roles & operations

Three roles share one codebase: a player who discovers and books, a facility owner who manages courts, amenities, and image galleries and watches analytics, and an admin who runs the venue-approval workflow — pending, approved, rejected — plus user management. Each sees a different slice of the same API, gated by the middleware I set up.

05

What I would change

Pre-materialising every slot as a row is simple and safe, but it doesn’t scale to many venues over a long horizon — I’d generate slots on demand from an availability rule and only persist the booked ones. And the venue-approval step should notify owners on decision, which we left manual under the clock.

Built with
React 18ViteReact QueryTailwindNodeExpressPrismaPostgreSQLJWTRazorpayCloudinaryNodemailer
← PreviousStackItNext →CAPS
You found the trick.
Thanks for
looking closely.
↑ ↑ ↓ ↓ ← → ← → B A · konami