Cafe POS
A full-stack restaurant point-of-sale covering table and floor management, fast billing, multi-method payments (cash, Razorpay, UPI QR), a real-time Socket.io kitchen display, and customer self-ordering by scanning a table QR. Role-based access spans admin, staff, kitchen, and customer.
Context
A small cafe juggles table service, order-taking, kitchen coordination, and payments across disconnected tools. Cafe POS folds them into one: front-of-house takes orders on a terminal, orders stream live to a kitchen display, customers can self-order by scanning a table QR, and payments settle by cash, card, or UPI in the same flow.
A four-person team sprint. I was the front-end developer.
The real-time kitchen
The kitchen display is the piece that has to feel instant, and it runs on Socket.io with room-based broadcasting — clients join restaurant, kitchen, table, and order rooms, and events like order:new and order:statusChanged push a ticket across New → Preparing → Ready columns without a refresh.
On the client side that’s my useWebSocket hook feeding the kitchen and customer layouts, so a status change on the floor and a new order from a QR scan both light up the same board in real time.
My role, honestly
I owned the front-end foundation. My first commit scaffolded the whole client — a Radix-based UI component library, the shared layouts, the custom hooks (including the WebSocket one above), and the service/state wiring with Zustand. From there I built out the customer- and kitchen-facing pages: real-time table-status indicators on the floor plan, drag-and-drop category reordering, and the kitchen display shell. The backend, payments, and data model were largely teammates’ work; I consumed those APIs from the client.
Payments, three ways
Because a cafe takes money however the customer has it, checkout supports three paths: cash with denomination buttons and change calculation, card/UPI through Razorpay with server-side signature verification, and a generated UPI QR for scan-to-pay. The front end switches cleanly between them; the verification and the cash session bookkeeping live on the server.
What I would change
The socket client reconnects but doesn’t reconcile — if the kitchen display drops for thirty seconds it can miss a ticket rather than replaying missed events on reconnect. I’d add a short server-side event buffer keyed per room so a reconnecting board catches up, which matters more in a real kitchen than in a demo.