
Sompi — Local-first Money Tracker
( Role )
Designer & Developer (own product)
( Scope )
- The brand and logo
- The design file
- The Flutter app for six platforms
- The Drift and SQLite data layer
- Security — on-device encryption
- Argon2id
- Auto-lock
- Biometric unlock
- Hidden balances — PDF and Excel export
- Backup and restore
- Reading bank notifications
- The Bangla localisation
- The tests
- From unit and widget tests to a Playwright suite that drives the web build
( Stack )
- Flutter
- Riverpod
- go_router
- Drift
- SQLite
- SQLite WASM
- Argon2id
- local_auth
- excel
- flutter_local_notifications
- Playwright




( Brief )
Sompi started with one question — where did this month's money go? I wanted a tracker that works the way money works here: cash in the pocket, a bank account, bKash, a savings account, a loan to a friend. So everything is built around accounts. Every income, expense and transfer lands in one, and History walks down from the year to the month, the week and a single day laid out hour by hour.
( Approach )
I designed all of it myself — the logo, the brand blue, the Facebook page banner and a 25-artboard design file — and then built the app natively in Flutter from that file: every colour, radius and type style is a token, with light and dark themes and English and Bangla. It is local-first: no server, no online account, no telemetry. The data is encrypted on the device, the password becomes a key through Argon2id, and backups are versioned, checksummed .sompi files.
The newest feature reads bank notifications. When I pay with my City Bank card, Sompi picks up the payment notification and records the expense in the right account by itself. On top of the ledger sit reports with a trend chart and a category breakdown, real PDF statements and Excel exports, monthly plans, savings goals, recurring income and bills, and a book of what I owe and am owed.



( Challenge )
Money has to add up every time. Amounts are whole numbers of poisha, never floats. A balance is never stored: it is derived from the ledger with one SUM, so it cannot drift. A transfer is always two rows written in one database transaction, so half a transfer cannot exist, and the local date is kept beside the UTC time so an entry made at 11:50 PM stays on that day. Running one database on six platforms — SQLite through FFI on phones and desktops, SQLite compiled to WebAssembly in the browser — sits behind a single file.
( Responsibilities )
The brand and logo, the design file, the Flutter app for six platforms, the Drift and SQLite data layer, security — on-device encryption, Argon2id, auto-lock, biometric unlock, hidden balances — PDF and Excel export, backup and restore, reading bank notifications, the Bangla localisation, and the tests, from unit and widget tests to a Playwright suite that drives the web build.

