Case study

FundsFlow

A private ledger for money moving inside a trusted circle — who sent what to whom, what is still outstanding, and the holdings friends are carrying on your behalf.

  • Flutter
  • Dart
  • NestJS
  • TypeScript
  • PostgreSQL
  • Prisma
  • Firebase
Circle · October

₹9,300

net outstanding to you

3 friends
  • ARArjunowes you+₹12,500
  • PRPriyayou owe−₹3,200
  • RARahulsettled₹0
Monthly statement · Arjun₹ thousand
MayJunJulAugSepOct
  • Sent to Arjun · UPI receipt₹5,000
  • Vega Pharma IPO · 1 lot held by ArjunHolding
FundsFlow widgetupdated 2m ago

₹9,300 outstanding

Interactive illustration with sample data — not live market or customer information.

overview

Overview

FundsFlow is a personal ledger for people who lend within a close circle — friends and family who pass money back and forth, apply for IPOs on each other's behalf, and need one trustworthy record of where everything stands.

It pairs a Flutter mobile app with a NestJS backend over PostgreSQL, and is live on the Google Play Store. The app, the API, the data layer and the landing site were all designed and built in-house.

problem

The Problem

Informal lending runs on memory and chat threads. Amounts get forgotten, a repayment gets counted twice, and when a friend buys shares with your money it is unclear whether that cash is still “with them” or has become something else entirely.

FundsFlow set out to replace that with a record both sides can trust:

  • Capture every movement once, with the sender, receiver, amount and date — nothing else to get wrong.
  • Show a live balance per friend and a single total across the circle.
  • Treat holdings as part of the same ledger, so investing never looks like money going missing.
  • Make corrections visible and permanent rather than silently editing history.
  • Keep sensitive financial data private — on the server, scoped to its owner, never on a public URL.
key features

Key Features

A ledger per friend

Add the people you lend to and borrow from, then record each movement as sender, receiver, amount and date. Every friend gets a running balance and a full history.

Settle up and reverse

One tap pre-fills the exact transaction that clears a balance. Mistakes are reversed with a permanent counter-entry, so the record is never quietly rewritten.

Stock & IPO holdings

Track shares and IPO allotments a friend is holding on your behalf, see how long each position has been open, and roll up exposure by company across everyone.

Monthly statements

Pick any month and get opening balance, money in, money out and closing — per friend, derived from the ledger so a correction flows through every month after it.

Receipts attached

Up to five images or PDFs per transaction, kept in a private bucket with no public URLs — ownership is checked on every read and write.

Home screen widgets

Android widgets for what's in the circle, what's in holdings and the total, each stamped with when it was last refreshed.

architecture

Architecture

The Flutter app signs the user in with Firebase Phone OTP and from then on carries only a Firebase ID token. Every request goes to the NestJS API, which verifies that token with the Firebase Admin SDK and derives the user's identity from it — the client never states who it is, and never sees a database URL, a password or a storage key.

The API is the only thing that touches Supabase: PostgreSQL through Prisma for the ledger, people and holdings, and a private Storage bucket for receipts, with paths derived from the owning user and transaction. Balances, the dashboard total and monthly statements are all computed from the transaction log rather than stored, so there is no snapshot to drift out of date.

On the device, the app follows MVVM with Provider — views never call the network directly — and publishes the latest figures to native Android home screen widgets after each dashboard load.

tech stack

Tech Stack

Mobile App

Flutter · Dart — MVVM with Provider, go_router, Dio; native Android home screen widgets in Kotlin

Backend

NestJS · TypeScript (strict) — Prisma ORM, Swagger, Helmet, rate limiting

Data

Supabase PostgreSQL for the ledger; Supabase Storage (private bucket) for attachments

Auth & Platform

Firebase Phone OTP on the device, verified server-side with the Firebase Admin SDK

engineering highlights

Engineering Highlights

  • Money is stored as integer paise end to end — never a float — so balances reconcile to the rupee no matter how many entries are involved.
  • A strict trust boundary: the app only ever holds a Firebase ID token. The backend verifies it, derives the user from it, and is the sole holder of database and storage credentials.
  • Every query is scoped to the authenticated user at the service layer, and attachment access re-checks transaction ownership on each request.
  • Reversals are immutable and the transaction model has no 'type' field — direction is just sender and receiver, which keeps the ledger simple to reason about and audit.
  • Holdings are reconciled through the same ledger: investing moves cash to a holding and a sale moves it back, so the dashboard total never double-counts.
  • Launched on Google Play with a public landing page, a privacy policy, and release signing set up for ongoing updates.
outcome

Outcome

FundsFlow is a complete, shipped product: a Flutter app backed by a typed NestJS service and a relational data model, live on Google Play with a public landing page.

It turns informal lending into a ledger both sides can rely on, and demonstrates end-to-end ownership — mobile, API, database, storage, authentication and release — designed, built and launched in-house.

Need something built to this standard?

We take on web, mobile, and backend projects from idea to production.