Food & Beverage / Internal SaaS

One system from QR code to profit report

A complete restaurant operating system: customers order by scanning, staff bill in under fifteen seconds, cooks work a live ticket board, and the owner sees profit for any date range.

Client
Pizza Theory
Restaurant point-of-sale screen with an open order, menu grid and kitchen queue panel

What was the problem?

Order entry slow enough to build a queue during a rush, a kitchen that started cooking before payment confirmed and absorbed every mistake as wasted food, and customers interrupting staff to ask where their order was. Stock and expenses were reconstructed after closing rather than captured during service.

What made it hard

Commercially

  • Replacing a paper workflow without asking staff to learn complex software
  • Delivering POS capability without per-terminal licensing or dedicated hardware
  • Giving the owner profit rather than just sales

Technically

  • Invoice numbers that cannot collide when two cashiers and a QR customer confirm in the same millisecond
  • Four distinct user experiences over one shared data model
  • Real-time propagation across every open device with no refresh button
  • Keeping read performance constant as years of order history accumulate
  • Bridging a staff credential system to database-level security rules

Operationally

  • Billing fast enough to survive a rush
  • Cooks needing a screen with no prices and no customer data
  • Owner needing to add and remove staff without a developer or the Firebase console

At scale

  • A ledger that stays as fast in its third year as on day one

Security

  • Money fields must become immutable once an order is paid
  • A cook must not be able to reach billing or customer data by typing a URL
  • No database credentials may be exposed to a public, unauthenticated ordering page

What we built

A full-stack POS built end to end: sub-10-second order booking, a payment-gated kitchen flow so orders reach the kitchen only after payment, real-time customer notifications through placed, preparing and ready for pickup, automated invoicing, inventory, expense tracking, reports, role-based user management, custom menus and a kitchen module.

What it does

  • QR-code customer ordering with no login or app

  • Live kitchen queue position for the customer

  • Returning-customer recognition by phone number

  • Sub-15-second counter billing

  • Quick row of five most-ordered items from real history

  • Audio-haptic bill confirmation

  • Kitchen board with role-scoped ticket view

  • Eight-tile owner dashboard with live profit

  • Repeat-customer table with lifetime spend

  • Searchable invoice ledger with CSV export

  • Audit-trailed invoice editing with money lock on payment

  • Menu, add-on, inventory and expense management

  • Owner-managed staff accounts and roles

  • Branded A4 PDF and thermal invoicing

  • Star ratings tied to specific invoices

  • Command palette search across orders, menu and inventory

  • Installable PWA with platform-aware install flow

Engineering decisions

Choices that could have gone another way, and what each one bought.

  1. Invoice numbers that cannot collide

    Bill numbering is implemented as an atomic Firestore transaction — the counter read, the increment and the order write happen as a single indivisible operation, on the client for counter billing and through the Admin SDK for public QR orders, sharing one identical path scheme.

    Why it matters. Two cashiers and a QR-code customer can hit confirm in the same millisecond and still get PT-0041, PT-0042 and PT-0043. It also costs one round trip instead of two, so billing feels instant. Bill numbering is the one thing a restaurant cannot get wrong.

  2. A financial-integrity rule built into the workflow

    Money fields lock the moment an order is marked paid. Only the customer name and phone stay editable afterwards, and every edit is stamped with an author and a timestamp, displayed alongside the invoice number.

    Why it matters. That is the difference between a billing app and an app an accountant will accept.

  3. A date-partitioned ledger designed for year five

    Orders are stored on a hierarchical path — business, year, month, date, orders — so a single day's business can be read without touching a record from any other day, while collection-group indexes still allow instant search across all time.

    Why it matters. The app is intended to stay exactly as fast in its third year as on day one, rather than degrading as history accumulates.

  4. Two authentication systems, bridged invisibly

    Staff sign in with email and password against a bcrypt-hashed directory through NextAuth. That session is exchanged server-side for a short-lived Firebase custom token, which is what actually authorises database reads and writes.

    Why it matters. One login for the user, proper database-level security rules underneath, and an owner who can add and remove staff without ever touching the Firebase console.

  5. A service worker written for a financial app, not a blog

    Only content-hashed static assets are cached — never an API response, never a page, never anything user-specific — and the worker is versioned so a new deployment cleanly invalidates the old cache.

    Why it matters. A POS that serves a stale order total is worse than a POS that is offline.

  6. Role-based access enforced in three layers

    A central route-to-role map drives navigation gating, client routing guards and server-side API checks, with Firestore rules scoping every read and write to the owning business. Typing a URL you are not allowed to reach redirects you to your own home screen.

    Why it matters. A cook sees the kitchen board and nothing else — no prices, no customer data, no billing — enforced at every layer rather than hidden in the interface.

  7. Designed for the counter, not the desk

    Fifteen-second billing flows, thumb-reachable controls, a Quick row computed from real order history, a command palette searching orders, menu and inventory at once, and audio-haptic confirmation — a three-note chime plus vibration — so staff know a bill saved without looking at the screen.

    Why it matters. During a rush, staff are not looking at the screen. The system has to confirm through sound and touch.

Technical detail

Collapsed by default. Open whichever part you are evaluating.

Frontend
  • Next.js 15 App Router with React Server Components
  • TypeScript end-to-end
  • Tailwind CSS with shadcn/ui on Radix primitives
  • Approximately 45 components
  • Responsive to small phones with safe-area handling
Backend
  • Next.js API route handlers
  • Firebase Admin SDK for server-only public endpoints
Database
  • Cloud Firestore
  • Date-partitioned document paths: business → year → month → date → orders
  • Three purpose-built composite indexes for collection-group search by business, invoice and phone
Storage
  • Firebase-hosted menu imagery, compressed in the browser before upload
Authentication
  • NextAuth v5 credentials provider
  • bcrypt password hashing
  • JWT sessions with 30-day lifetime
  • Server-minted Firebase custom tokens bridging the staff session to database auth
Authorization
  • Central route-to-role map
  • Navigation-level gating
  • Client-side routing guards
  • Server-side API checks
  • Firestore security rules scoping every read and write to the owning business
Caching
  • Custom service worker caching only content-hashed static assets — never an API response, page or user-specific content
  • Versioned worker so a deployment cleanly invalidates the previous cache
Messaging
  • SMS templates and provider configuration for invoice dispatch
Deployment
  • Vercel with environment-driven configuration
Monitoring
  • Install-prompt analytics tracking intent, dismissals and completions

Frontend
  • Next.js 15
  • React Server Components
  • TypeScript
  • Tailwind CSS
  • shadcn/ui
  • Radix UI
Backend
  • Next.js API routes
  • Firebase Admin SDK
  • NextAuth v5
Database
  • Cloud Firestore
Cloud
  • Vercel
  • Firebase
Integrations
  • SMS provider (configurable)
Tools
  • ESLint 9
  • Vitest
  • React Testing Library

Authentication
  • bcrypt-hashed staff credentials
  • JWT sessions with a 30-day lifetime
  • Staff session exchanged server-side for a short-lived Firebase custom token
Authorization
  • Three roles — Super Admin, Reception/Cashier and Cook
  • Enforced in navigation, in client routing, and at the API layer
  • Staff management endpoints reject non-admin sessions outright
  • A cook signing in lands on the kitchen board and can reach nothing else
Data protection
  • Firestore security rules scope every read and write to the owning business
  • Public ordering endpoints run server-side through the Admin SDK so no credentials reach the browser
  • The kitchen surface exposes no prices and no customer data
Auditability
  • Every invoice edit stamped with author and timestamp
  • Editor attribution displayed alongside the invoice number
Privacy
  • Customer records keyed by phone number; no account or password required of customers

Mechanisms

  • Atomic transactional invoice numbering
  • Real-time Firestore onSnapshot listeners across all surfaces
  • Service worker that never caches API responses or user-specific content
  • Graceful error states throughout

Failure scenarios handled

  • Concurrent billing from two terminals and a QR customer simultaneously
  • Missing Firestore index — surfaced with a direct link to create it
  • Stale cache after deployment — prevented by worker versioning

Idempotency. Invoice issuance is transactional, so a number is consumed exactly once regardless of concurrency.

Before and after

Before

  • A billing book, a calculator, a phone for order calls and a notebook for expenses
  • Customers repeatedly asking counter staff whether their order was ready
  • Sales and expenses tracked separately, so profit was never visible in one place
  • Off-the-shelf POS priced per terminal per month and locked to specific hardware

After

  • One record moving from QR-code order to kitchen ticket to paid invoice to profit line
  • Customers watching their own position in the kitchen queue
  • Live profit for any date range, with expenses folded in
  • A system running on the devices the restaurant already owned, with no licence fees

The build, by the numbers

What was built, at what scale. These describe the system's size, not its business results.

role-specific surfaces
4role-specific surfacesCustomer, reception, kitchen and owner — one shared live data model
enforcement layers for access control
3enforcement layers for access controlNavigation, client routing and server-side API checks
live dashboard tiles
8live dashboard tilesIncluding profit computed live from sales less expenses
per-terminal licence cost
0per-terminal licence costRuns in a browser on devices the restaurant already owns

What changed as a result?

Orders booked in under 10 seconds. The payment-first kitchen queue eliminates unpaid and incorrect orders, and customers stay informed in real time until pickup — a fully automated shop-floor system.

  • Order booked to invoice in under 10 seconds
  • Kitchen queue gated on payment, so unpaid orders cannot reach the line
  • Customers notified automatically at each stage, removing status interruptions

What we can evidence

Orders booked in under 10 seconds

Why does this matter in restaurants & food service?

Restaurant software is the system that takes an order, bills it, tells the kitchen and records what it cost you — and it is judged at the counter during a rush, not in a demo. If booking an order takes thirty seconds, the queue builds and staff work around the system instead of through it. We built the Pizza Theory POS end to end.

  • Order entry slow enough to build a queue

    Every extra second per order compounds across a dinner rush. The Pizza Theory POS books an order in under ten seconds, which is the difference between the system helping and the system being bypassed.

  • Unpaid and incorrect orders reaching the kitchen

    A kitchen that starts cooking before payment confirms absorbs every mistake as wasted food. A payment-gated queue means an order only reaches the kitchen once it is paid for.

  • Customers asking staff where their order is

    Every status question interrupts someone working. Real-time notifications through placed, preparing and ready-for-pickup remove almost all of those interruptions.

  • Stock and expenses reconciled after closing

    Counting stock and totting up expenses at the end of a shift is where margin quietly disappears. Inventory and expense tracking inside the POS make the numbers a by-product of service.

More on what we build for restaurants & food service

See it running

pizza-theory.vercel.app(opens in a new tab)

Need something like this for restaurants & food service?

Tell us what is slowing the business down and we will tell you whether software is the right fix. If it is not, we will say so.

Ask a Quick Question on WhatsApp

Free 30 minutes · no obligation

WhatsAppCall