Corner Shop Register
Offline-first register, stock and credit ledger for a neighbourhood grocer. No internet, no server.
How this was measured: Test count from vitest output, tables from migration files, LOC via wc over tracked source files.
- WINDOW
- kasa ekranıReact + Vite
- PIN kilidiscrypt
- MAIN
- Electron main
- fiş şablonu
- LEDGER
- stok defterisatır, sayaç değil
- FILE
- SQLiteWAL · 18 tablo
Problem
A neighbourhood grocer does not run on subscriptions. The till must work when the line is down, the day must close with a printable Z report, and the credit notebook — who owes what, since when — is the real accounting system.
Every cloud POS I looked at assumed a connection and a monthly fee. This one assumes neither.
Constraints
- Fully offline: no API, no account, no telemetry.
- One machine, one operator: a 4-8 digit PIN with scrypt, auto-lock after two idle minutes.
- Data lives in a single SQLite file under the OS user data directory, WAL mode.
Architecture decisions
SQLite as the source of truth, not a cache
The register writes to the same file the reports read. No sync layer, so no reconciliation bugs — and no multi-device story, which is a deliberate trade.
Cost: No second till without a redesign of the write path.
Stock is a ledger, not a counter
Purchases, sales and manual corrections are rows; the on-hand number is derived. A counter column drifts the first time someone cancels a receipt.
Cost: Every stock query aggregates; mitigated with indexes and a reconciliation check.
Receipts are templates, not screenshots
The Z report and the customer receipt render from a template that knows the paper width, so a 58mm and an 80mm printer both work.
Cost: A small layout engine instead of print CSS.
Four smoke tests against the real Electron app
Unit tests cover the ledger; CDP-driven smoke tests open the actual window and click through register, stock, credit and closing.
Cost: Slower CI, but the failure mode that matters — a broken window — is caught.
Proof
- Unit tests233 (31 files)
- Schema tables18
- Smoke tests4 (POS, stock, credit, Z report)
- Source files150
Known limits
- Windows packaging and backup/restore are not finished; the app runs from source today.
- No real shop has used it for a month — there is no field data in this case.
- Single-terminal by design; sync is out of scope, not forgotten.
What I learned
Offline is not a feature flag. Once you remove the server, every assumption about identity, time and conflict comes back as a local problem — the PIN, the clock and the file lock all become part of the architecture.