02 / Pitched & built solo · live
Bunny’s Cafe
A real-time ordering system for the cafe behind my college, pitched and built solo. QR-code table entry, phone OTP auth, live order status, Razorpay checkout, and an admin dashboard the owner actually uses.
- Role
- Pitched, designed & built solo
- Stack
- Next.js, Prisma, PostgreSQL, Razorpay
- Live
- bunnyscafe.in

01The problem
The cafe behind my college was jammed every lunch break: one counter, one queue, and forty minutes of class between orders. The bottleneck was not the kitchen, it was students standing in line to say what they wanted.
I pitched the owner on replacing the line with a phone in every student’s hand, then built and shipped the whole system myself: menu to kitchen to payment to handoff, with nothing bolted on from a third-party ordering platform.
02How it works
Order
A QR code on the table opens the menu in the browser, no app install. Items, variants, and add-ons are configured in an admin panel, with per-order price snapshots so a later menu change never rewrites a past receipt.
Verify
Firebase phone OTP, rate-limited to 3 requests per phone-and-IP pair in a 5-minute window. A successful login sets a 7-day httpOnly JWT cookie so a regular does not re-verify every visit.
Pay
Razorpay checkout or cash at the counter. Online payments are verified server-side by recomputing the HMAC-SHA256 signature before an order is ever written, so a forged client payload cannot mark itself paid.
Track
The order screen holds open a Server-Sent Events stream that polls the database every 1.5 seconds and only pushes a diff when the order actually changes state, with Web Push as a fallback so a closed tab still gets notified when the order is ready.
03Behind the counter
The kitchen side got the same amount of attention as the ordering flow: a kanban board for incoming orders, a walk-in POS for the counter when a customer skips the QR code entirely, coupon codes with per-order minimums and usage caps, and a sales dashboard the owner can filter by day, week, or month to see cash versus online split.
04Result
- Checkout completion after launch
- +35%
- Order status refresh, diffed not polled blind
- 1.5s
- Commits shipped solo, requirements to handoff
- 195
05What I would change next
Order status updates by polling the database every 1.5 seconds and diffing the result before pushing. It works, and it is honest about what SSE on a serverless platform can do without a persistent backend, but a proper LISTEN/NOTIFY channel or a queue would replace the poll with an actual push and cut the delay further.