Skip to content
Food & HospitalityClient work

A-RICE — Billing System

Client
A-RICE
Year
2026
Format
16:9
Disciplines
Software & Internal Tools
A-RICE — Billing System

Overview

Offline-first billing application for the A-RICE counter in Nagpur. Tap a dish, press Generate Bill, print. The bill is written to a real SQLite database on the device before anything touches the network, so the counter keeps working when the connection does not. Supabase holds a copy, never the original.

“The till cannot wait for the internet.”

Specification

Built with
React 19, TypeScript, Vite, SQLite (WASM, OPFS), Supabase Postgres, Tailwind CSS v4
Delivered
  • Billing counter with catalogue and search
  • GST invoicing and thermal printing
  • Customers, inventory and day-sales reporting
  • Offline queue with multi-device sync

The challenge

A restaurant till has one requirement that overrides every other: it must take the money. Not usually. Every time, including during the lunch rush, including when the broadband is down.

That rules out the normal shape of a web app, where the database is somewhere else and a bill is an HTTP request that might fail. It also rules out the usual offline fallback — browser storage — because a day's takings held in a cache that a cleared browser can delete is not an accounting record.

And the numbers have to survive an audit. Invoice sequences cannot have holes, a voided bill cannot quietly change its own total, and a rounding error repeated across a year of lunches is a real amount of money.

The approach

Bills are written to an actual SQLite database on the device, stored through OPFS and running inside a Web Worker — the synchronous file APIs SQLite needs exist only in workers. The local database is the source of truth; Supabase is a backup and a multi-device copy. Nothing in the billing path waits on the network.

One module is the only write path. It saves the row and queues the outbox entry in a single transaction, so a bill and its sync record cannot disagree — there is no state where the counter has taken money the cloud will never hear about.

Money is stored as integer paise and quantity as integer milli. Nothing is ever a float, so nothing accumulates a rounding error.

Invoices are append-only. Voiding sets a status and never edits an amount, and numbers are never reused. Bills snapshot the item name, rate and GST at the moment of sale, so repricing a dish tomorrow cannot rewrite what a customer paid today.

Sync pulls before it pushes, which is what lets a second device inherit the catalogue and the invoice sequence instead of starting its own.

The outcome

A counter that bills and prints with no internet at all, and reconciles itself when there is one.

Invoice numbering follows the Indian financial year and resets each April, alongside a daily token number for the customer. Generate Bill prints immediately — no preview step, no second click.

In use at A-RICE, Nagpur.

What it delivered

  • Bills save and print with the network fully down
  • Local SQLite is the source of truth, not a cache
  • Integer paise throughout — no floating-point money
  • Append-only invoices; a void never rewrites an amount
  • Second device inherits catalogue and numbering on first sync