appscript.dev
Blog Sheets Gmail

How I built a personal finance dashboard

Pulling every account into one live Northwind treasury view — a Sunday-afternoon build that pays itself back monthly.

By Awadesh Madhogaria · Published Jul 20, 2025

Running Northwind, I always roughly knew our financial position. “Roughly” is a bad word when you are deciding whether to take on a hire or a big expense. The numbers existed — they were just scattered across banks, Stripe, and a savings account, each behind its own login.

To answer “how much runway do we have?” I had to log into three or four places and do arithmetic in my head, so I did it rarely. That gap had a cost: decisions got made on a stale, optimistic mental estimate, a slow month did not register until I happened to check, and I never had a clean week-over-week picture of cash burn versus revenue. I did not need fancier accounting — I needed one screen that was always current. So one Sunday afternoon I pulled everything into a single live view.

What’s in it and how it gets data

The dashboard is a single Google Sheet with three things on the front tab: current balances per account across banks, Stripe, and savings; the last 30 days of transactions, categorised; and net cash burn versus revenue, week over week. That is the whole treasury view — one tab, always up to date, no logins.

Each source feeds the sheet a different way, chosen for how much friction it was worth. Stripe arrives cleanly via its API. Banks come in by parsing their transaction alert emails — no Plaid, because Plaid is overkill for a one-person setup. And a manual reconciliation row at month-end catches anything the automation missed. The bank-email parsing is the scrappy part, and I am fine with that: it is free, it needs no extra vendor, and a wrong row gets corrected at month-end.

What kept the whole thing maintainable was one design rule — never let one source touch another’s data:

  1. Each source has its own small “puller” function.
  2. Each puller writes only to its own dedicated tab.
  3. The dashboard tab uses QUERY to combine those tabs into the live view.

So when a bank changes its email format, I fix one puller and nothing else breaks. A new account is just a new puller and a new tab, and the dashboard absorbs it.

What I’d do differently

Start with one currency. I tried to make the dashboard multi-currency from day one, and I spent more time wrestling FX rates and conversion edge cases than I spent on the actual dashboard. The multi-currency layer was a problem to solve after the simple version was proving its worth — not before.

And it did prove its worth quickly. One screen now answers “where do we stand?” in seconds, any day; cash decisions run on live numbers instead of a hopeful mental estimate; and although it was only a Sunday-afternoon build, it earns that time back every month.

The takeaway

A finance dashboard is not really a finance project — it is a plumbing project. Build one honest puller per source, keep them isolated, and let a QUERY do the assembling. Resist the urge to solve every edge case before the plain version exists.