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

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
Next project
NIKE AIR ZOOM PEGASUS 40
Sportswear & Footwear/2025
