The problem
Cobalt's first POS was three separate tools: one for orders, one for the kitchen, one for reporting. Waiting staff kept two tabs open and still had to ring the kitchen to confirm anything. New hires took most of a week before they stopped asking for help.
The brief was blunt: one screen, learnable in a single shift, usable on the cheap Android tablets already on the floor.
What I built
- A single-page order flow where the menu, the cart and the checkout never leave the screen.
- A kitchen display that pushes state over WebSockets, with an optimistic queue so a dropped connection on restaurant Wi-Fi never loses an order.
- Table management with a floor plan staff can drag to match the actual room.
- Stock deduction tied to the recipes, so the owner finds out they are out of prawns before the customer does.
- A reporting view that answers the three questions owners ask daily: what sold, what it cost, what's left.
Decisions worth explaining
Server state, not global state. Orders live in TanStack Query with a WebSocket invalidation channel. There is no Redux store duplicating the database, which removed a whole category of "the screen says something different from the kitchen" bugs.
Offline-tolerant, not offline-first. Full offline sync would have doubled the budget. Instead, order submissions queue in IndexedDB and flush on reconnect — covering the twenty-second Wi-Fi drops that actually happen, without the conflict resolution a true offline product needs.
Rendered for tablets first. Every list is virtualised and the whole app is budgeted to 180 KB of JavaScript, because the target device is a three-year-old Android tablet, not a MacBook.
Results
- Average order entry dropped from 48 seconds to 19.
- Training time fell from five days to one shift.
- Support tickets about "the kitchen didn't get it" dropped by 86% in the first quarter.