Most restaurants do not have a software problem. They have five software problems, and none of them talk to each other.
That was the observation behind FoodCiti — and the reason we spent the past year building it. This is the story of what we found, what we built, and what it looks like now that real restaurants are running their evenings on it.
The problem nobody names
Walk into an independent restaurant on a Friday night and count the screens. There is a till for the people at the tables. A tablet from a delivery marketplace, beeping. Possibly a second tablet from a second marketplace. A laptop somewhere with the website's orders. A paper diary for reservations. And a spreadsheet, updated on Sunday, that is supposed to tell the owner how the week went.
Each of those tools works. That is what makes the problem so easy to miss. The failure is not in any one system — it is in the space between them:
- An online order arrives on a tablet and has to be re-typed into the till. Someone mistypes it.
- The kitchen gets dine-in tickets on one printer and delivery on another, so nothing is sequenced by when it actually needs to leave.
- The marketplace takes its cut, and it owns the customer — the restaurant never learns who ordered.
- Sunday's spreadsheet disagrees with the till, which disagrees with the marketplace dashboard. Nobody knows which is right.
Every one of those gaps costs money, and none of them appear on an invoice. That is the integration tax: paid in lost orders, re-keyed data, stacked subscriptions and decisions made on figures nobody trusts.
The bet we made
FoodCiti's hypothesis was blunt: own the entire operation in one platform and the friction between systems simply stops existing.
Easy to say. The difficulty is that "the entire operation" is not one product. It is more than a dozen distinct surfaces — a till, an ordering site, a kitchen display, a driver app, a reservation diary, stock control, loyalty, reporting — each with its own real-time demands, spread across web, mobile and desktop.
Building one of those well is a project. Building all of them, so they genuinely share one source of truth, is a different order of problem. That is the part that inspired us, and it is the part that took the work.
The idea the whole system rests on
There is one architectural decision underneath everything else, and it is almost embarrassingly simple.
Every order is the same kind of thing, no matter where it came from.
An order placed on the restaurant's website, an order rung into the till, and an order taken at a table are one record in one pipeline, distinguished by a single field. They move through the same states — pending → confirmed → preparing → ready → out_for_delivery → completed — and they arrive in the kitchen in the order they actually need to be cooked.
That one decision is what makes the rest possible. Reporting does not need to reconcile three systems, because there are not three systems. The kitchen does not need to merge two queues. The customer record is the same customer whether they walked in or ordered online. Nothing has to be re-keyed, because nothing was ever in a second place.
What we built
On top of that pipeline sits the operation:
- EPOS, on the counter and in the hand. A Flutter till for Android and iOS, an Electron desktop POS for Windows, and mobile order-taking for tableside service.
- Branded online ordering on the restaurant's own domain — their customers, their data, no marketplace commission.
- Table reservations and floor management, in the same system that runs the service.
- Kitchen workflow that sequences every channel into one queue.
- Delivery dispatch with driver assignment, distance and delivery-charge calculation, and a dedicated driver app.
- CRM, loyalty and promotions — customers, coupons, offers and meal deals, native rather than bolted on.
- Inventory and supply chain — ingredients, recipes, stock counts, suppliers and purchase orders.
- Reporting by day, by postcode, by customer and by channel, exportable to PDF and Excel.
The stack is Angular on the front, Node and Express over MongoDB behind it, Flutter for mobile, Electron for the desktop till, Socket.IO for everything real-time, and AWS for storage. Payments run through PayPal, DNA Payments and Teya, with refunds handled automatically.
The hard part was not the features
It was the network.
A restaurant's Wi-Fi is not a data centre. The router is behind the bar, the till is at the far end of the room, and at eight on a Saturday the connection drops for four seconds. In most systems that is when an order goes missing — it was pushed to a device that was not listening, and nobody notices until a customer rings to ask where their food is.
So the real-time layer is built on the assumption that devices will disappear. Each POS device holds a heartbeat, and when one reconnects the server replays the orders it missed rather than trusting that the original push landed. A flapping connection can fire a reconnect a dozen times in as many seconds, so replays are debounced per device — otherwise the fix becomes its own problem and the kitchen gets the same ticket twelve times.
None of that is visible in a demo. All of it is the difference between a system a restaurant trusts on a Saturday night and one they quietly stop using.
Where it is now
FoodCiti is live and running real services:
- 20+ restaurants operating on the platform
- 20,000+ customers served through the online ordering system
- One system in place of the five most of them started with
Those are orders that arrived on a restaurant's own site, went straight into the same queue as the walk-ins, and left the kitchen in the right sequence — with the customer's details staying with the restaurant rather than a marketplace.
What it taught us
Three things we have carried into everything since.
The integration is the product. Anyone can sell a till or an ordering widget. The value was never in a single module; it was in collapsing a dozen tools into one pipeline so the gaps between them stop existing. When we scope a platform now, we start with the seams.
Design for the bad night, not the demo. The reconnect logic, the replay buffer, the debounce — none of it shows in a screenshot, and all of it is why the system holds when the Wi-Fi does not. Software that runs an operation has to assume the operation is messy, because it is.
Owning the customer matters more than owning the order. Restaurants had accepted that the marketplace keeps the relationship. Putting ordering on the restaurant's own domain changed what a repeat customer is worth to them, and that turned out to be the argument that landed hardest.
FoodCiti is one of two platforms we build and operate ourselves. Running our own products in production is a deliberate choice: it means we live with our architectural decisions on a Friday night, the same way our clients do.
We build systems businesses actually run on — and we run two of our own. If you have an operation held together by five tools that do not talk to each other, tell us about it.




