PERSONAL PRODUCT · MOBILE

Fluid Ledger

A personal finance app designed for the messy reality of money data: bank messages, intermittent networks, shared expenses, and a need to trust the numbers.

RoleProduct & Engineering
PlatformFlutter / Android
Account accessSupabase phone OTP
View source on GitHub ↗

Product context

Make spending visible before it becomes vague.

The problem

Personal finance usually starts with incomplete signals: a bank message, an expense someone paid for, or a cash purchase remembered later. Fluid Ledger turns those fragments into a reviewable ledger without assuming the phone will always have a stable connection.

What the product does

The app supports manual expense entry, explain-first Smart Sync for bank-SMS imports, merchant categorization and overrides, searchable history, monthly spending analytics, budgets, savings goals, weekly targets, local notifications, CSV/JSON export, and a dedicated shared-expense workspace.

Engineering posture

SQLite is the local source of truth. Supabase is used when a signed-in user has a connection, with delta sync, serialized operations, pending-write flushing, and bounded retry handling. A weak network becomes a recoverable state—not a reason to lose an expense or show misleading totals.

Product modules

Built as connected money workflows, not a single expense form.

Each module owns a distinct user problem, while sharing one local ledger and a synchronization model designed for Android’s unreliable real-world conditions.

01 / CAPTURE

Transaction intake

Manual entry is always available for cash and missing records. Smart Sync explains why SMS access is needed before requesting Android permission, then scans supported bank and UPI debit messages. The parser extracts amount, direction, date, merchant, sender, and reference information while deliberately rejecting OTP, promotional, balance, and loan messages.

02 / CLEANUP

SMS parsing & categorization

Different institutions describe the same spend differently. The parser handles rupee formats, UTR or reference values, card spends, UPI handles, and merchant patterns. A fingerprint built from time, amount, and reference or normalized merchant helps collapse duplicate bank-and-UPI alerts while preserving the richer record. Merchant intelligence canonicalizes common names and uses fuzzy matching to suggest matches; manual merchant overrides and category changes keep the user in control.

03 / UNDERSTAND

Ledger, history & insights

The recorded transaction becomes one item in a local ledger: browseable by time, category, and search context. Dashboard analytics use the full current-month dataset, while the recent-activity feed stays intentionally concise. Configurable categories prevent the UI from forcing every purchase into a generic bucket. Export can share the same transaction data as CSV or JSON rather than trapping it inside the app.

04 / PLAN

Goals & weekly targets

Savings goals track a target amount, saved progress, and remaining amount. Weekly targets watch a category-specific limit and combine ledger activity with manually logged off-app spend, so a budget is not falsely “safe” just because a purchase happened outside a bank feed. Local notifications can report completed scans and scheduled weekly summaries.

05 / SHARE

Groups — the Splitwise-style module

Shared expenses are modeled separately from a personal transaction. A group contains members, split expenses, individual shares, and settlement history. While entering an expense, a payer and participating members are selected, then the total can be divided equally, by percentage, or as explicit amounts. The app calculates outstanding balances and simplifies debts into the smallest practical set of repayments, then lets a settlement be recorded optimistically so the UI responds immediately.

  • PeopleMembers can be added from device contacts, saved contacts, or manually—useful when a group is assembled in the moment.
  • ExpensesEvery shared bill keeps its participants, payer, chosen split method, and resulting individual obligations.
  • Settle upOutstanding balances and the activity feed make it clear who owes whom; recorded settlements bring the group back to a known state.
06 / RECOVER

Offline-first sync & realtime consistency

Transaction, goal, target, and group data are cached in SQLite. When connectivity returns, operations are serialized so overlapping pulls and pushes cannot leave projections half-updated. Delta sync begins from the latest known transaction timestamp; a stale or malformed local state can fall back to a full rebuild. Pending writes are flushed with bounded retry. For groups, Supabase Realtime listens for changes to groups, members, expenses, splits, and settlements, coalesces quick bursts of events, and refreshes only affected group projections instead of reloading every screen.

System concerns

Flutter, Riverpod, SQLite, Supabase / PostgreSQL, Realtime, Android SMS, local notifications — mobile data capture, transaction normalization, local-first persistence, sync recovery, and explainable financial views.

PERSONAL PRODUCT

Built as a practical finance system where the value is not only tracking a transaction, but making its origin, category, sync state, and shared impact understandable.