Sangsar — Household Finance PWA
A private, bilingual (বাংলা / English), offline-capable money and life-admin app for a two-person household.
- Role
- Designer & engineer
- Team
- Solo
- Timeline
- Sep 2026 – Oct 2026
- Organisation
- Personal
- Code
- Private repository
- Reading time
- 3 min
Log any money movement in about ten seconds in either language, then see the month at a glance. A repository layer swaps IndexedDB for Firestore, offline writes sync safely, and 760 unit tests plus 11 end-to-end flows keep it honest.
Overview
Most finance apps assume English, cards and a bank feed. A Bangladeshi household runs on cash, bKash and bank transfers, thinks in lakh, and writes in Bengali. Sangsar is built for exactly that — and for two people sharing one book.
The problem
- Entries must take seconds, in either language, on a phone.
- Two devices edit the same data, often offline.
- Some notes are private to their author, even within the household.
Context & constraints
Android-first, used daily, deployed as a static PWA backed by the household's own Firebase project.
Approach
- Fast entry — the amount field accepts Bengali digits and inline arithmetic (
120+45×2); optional line items, shop, payer, need-vs-want, tags, receipt photos (compressed under 350 KB) and quick-add templates. - Everything in one place — wallets (cash, bKash/Nagad/Rocket, bank, card), savings goals, monthly budgets, recurring bills with idempotent auto-posting, loans, shared shopping lists that become expenses, events on the Bangla calendar, notes and a message board.
- Insights & reports — cash flow, category donut, trends and weekday patterns with a table view for every chart; branded PDF statements with correct Bengali rendering, CSV and JSON backup.
- One repository, two backends — the UI only talks to hooks and selectors; a
Repointerface is implemented by IndexedDB (development) and Firestore (production, loaded on demand).
Key capabilities
- Bengali numerals, lakh grouping and Avro-compatible fonts
- Inline arithmetic in the amount field
- Offline entries queued and synced when back online
- Conflict notices when the other phone changed the same item
- Private notes enforced by server-side rules
- PDF statements with correct Bengali shaping
Architecture
Interface
Repository
Sync & offline
A repository interface keeps storage swappable; the server enforces the rules that matter for two devices. Select a component to trace its connections.
Key decisions
ADR-01Field-level patches with stale-write refusal
- Context
- Two phones editing offline will eventually collide.
- Decision
- Send field-level patches; the rules refuse writes older than the stored copy, and the app checks the server copy to tell a real conflict from an error.
- Trade-offs
- More rule logic, but no silent overwrites — and one clear notice per burst of conflicts.
ADR-02Private notes as two queries
- Context
- Rules that filter documents per reader can’t be bypassed by a single query.
- Decision
- Read shared notes and the reader’s own private notes separately, then merge.
- Trade-offs
- Two listeners instead of one; privacy enforced by the server, not the UI.
Challenges
Bengali in PDFs
Problem. Many PDF pipelines break Bengali conjuncts.
Solution. Statements render through the browser’s own text shaping before conversion, so conjuncts survive.
Quality & delivery
Testing
760 unit tests in 57 files (Vitest), Firestore-rules tests against the emulator, and 11 Playwright flows — plus a script that runs the production build on several simulated devices against the emulators to prove multi-device behaviour.
Deployment
A setup script provisions the Firebase project, database, rules and accounts; a packaging script refuses to build without a complete configuration and outputs a static folder for drag-and-drop hosting.
Outcome
- Unit tests
- 760
- 57 files
- End-to-end flows
- 11
- Plus multi-device emulator runs
- Routes
- 26
- 14 feature areas
- Languages
- 2
- Key parity enforced by a test
In daily use by the household it was built for, across two Android phones, with shared data that survives offline days.
Lessons
- Offline-first is mostly about conflicts, not caching.
- Treat translation keys like an API: test them.
Building something similar?
Tell me what you’re working on — I reply to every serious message.
Related work
খোঁজ Khoj — Million-Line Text Reader
One Web Worker per file streams 16 MB slices, indexes line offsets in typed arrays and runs cancellable searches; a custom virtual reader scrolls millions of lines without hitting the browser’s maximum element height.
- TypeScript
- React
- Vite
- Web Workers