Projects/sitzy
Professional / Company project
SITZY
Library discovery and seat booking platform
Students find study libraries, book a daily, weekly, or monthly place, pay, and check in with a QR. Owners list branches, manage capacity, and scan arrivals; admins approve listings.
- React
- Next.js
- Node.js
- NestJS
- PostgreSQL
- FCM
Bookings · Capacity · Check-in · Payments
Overview
SITZY is a three-sided NestJS + PostgreSQL platform with Next.js portals for library owners and super admins. Students (mobile API) browse approved libraries, reserve one place on a workspace, pay via Razorpay or COD, and present a QR at the door. Owners onboard listings, set capacity and prices, take walk-in bookings, and check people in. The API enforces capacity per calendar day, a 10-minute unpaid hold, branch-scoped check-in, and encrypted per-owner Razorpay keys.
Problem
Study libraries sell shared rooms, not labelled chairs. Without a single capacity calendar, two people can pay for the last place, unpaid checkouts leave inventory lying, and door staff have no reliable way to prove a booking is valid for this branch today.
Solution
Inventory is workspace capacity, not seat numbers. A booking occupies one place for every date in the plan. Online creates a 10-minute hold; confirm re-checks capacity and issues a booking code plus a secret QR token. Check-in is lookup-then-confirm under a row lock. Listings stay out of the catalog until an admin approves them. Online charges settle to the owner's Razorpay account when configured, and a ledger records student → owner.
Key features
- Approved-library catalog and nearby search
- Workspace capacity with daily, weekly, and monthly plans
- Pre-booking validation and 10-minute online payment hold
- Razorpay checkout to owner or platform merchant keys
- COD front-desk booking and mark-paid
- QR token check-in with booking-code fallback
- Owner occupancy, bookings, and check-in portal
- Library onboarding wizard with geocoded address and document upload
- Admin approve / reject / suspend listings
- Favorites and reviews after completed bookings
- JWT auth with OTP, Google, and Apple mobile login
- In-app notifications and FCM push
Technical challenges
Problem
Last place can be claimed twice if unpaid bookings do not occupy inventory.
Approach
pending_payment holds capacity for 10 minutes. Confirm-payment re-checks availability excluding that hold; if the range is full the booking expires instead of confirming.
Problem
Two devices can scan the same QR at the same moment.
Approach
Scan is preview-only. Confirm reloads the row with SELECT … FOR UPDATE, re-runs eligibility, then writes checked_in. The second request gets a conflict.
Problem
A weekly or monthly plan is useless if any day in the range is full.
Approach
Availability is computed per calendar day. Any full day rejects the entire booking and returns the conflict dates.
Problem
Online fees should reach the library's merchant without exposing the secret.
Approach
Owners store Key ID plus an encrypted Key Secret. Checkout and signature verify use that merchant (or platform keys). Secrets are never returned to the client.
What this demonstrates
A multi-sided booking product: capacity inventory, payment holds, QR check-in, listing approval, and separate owner/admin portals on one NestJS API.