Skip to content
In productionFull stackTools

Sangsar — Household Finance PWA

A private, bilingual (বাংলা / English), offline-capable money and life-admin app for a two-person household.

React 19 PWAHooks & selectorsRepo interfaceLocal repoCloud repoPersistent cacheSecurity rulesService worker
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 Repo interface 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

  1. Interface

  2. Repository

  3. 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

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

Virtual readerLine cacheSearch UISlicerLine indexSearch
Completed2026Personal

খোঁজ 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