Domdhi logoDOMDHI.OS
FINANCE

Building Your Own Financial Dashboard

Four numbers on one screen: net worth, monthly burn, runway, and days to FI. Everything else is decoration. Here's the data model, the three hard parts nobody warns you about, and why staleness is the bug that actually matters.

DDominic BacaSOLO ENGINEER · DOMDHI.OS2026.11.055 MIN READ
FINANCE// FIG.01

I don't use Mint, YNAB, or Personal Capital. So I built the thing they'd be doing for me.

This is what I learned constructing it, and specifically the three problems that only show up after you start.

Four Numbers. That's The Whole Product.

The temptation is to build everything — spending by category, pie charts, month-over-month trend lines, a projection curve. I did some of that. Almost none of it changed a decision.

What earns a place on the screen:

Net worth. Assets minus liabilities, one number. The only honest scoreboard, and the one that's useless day to day and essential quarterly.

Monthly burn. What actually leaves per month. This is the load-bearing figure — freedom number is burn × 25, emergency fund is burn × months, runway is savings ÷ burn. Get this wrong and every derived number is wrong by the same multiple.

Runway. Accessible assets ÷ burn. How many months you could survive with zero income, starting now. Note the word accessible — a 401(k) is not runway.

Days to FI. The single metric that compresses everything into one integer that can go up or down.

That's it. If a number can't change a decision, it's decoration, and decoration on a financial dashboard is actively harmful — it dilutes attention from the four that matter.

The Data Model

Simpler than people expect. Three concepts:

Accounts — a balance, a type (retirement / taxable / cash / crypto / liability), an accessibility flag, and a last_updated timestamp. That last field is the most important column in the whole schema and I'll explain why below.

Snapshots — an append-only history of balances over time. Never mutate a balance in place; write a new snapshot. You want the trajectory, and you want to be able to reconstruct what you believed on any past date.

Derived values — burn, runway, net worth, days to FI. Compute these, never store them. A stored derived value is a value that will be wrong eventually, because something upstream will change and nobody will remember to recompute it. Derive on read, always.

The accessibility flag matters more than it looks. Mine reveals that 78% of my assets are locked in retirement accounts — a number I did not want to see and could only see because the schema forced the distinction.

Hard Part 1: Staleness Is The Real Bug

This is the one that separates a useful dashboard from a dangerous one.

A dashboard showing a number always looks correct. There is no visual difference between a balance updated this morning and one updated in March. Both render as confident text. And you will make decisions on it.

This is the exact failure mode of the commercial aggregators — a bank connection silently breaks, the balance freezes, the UI keeps rendering it, and you're three weeks stale without knowing.

So: every value renders with its age, and stale values look wrong.

  • last_updated is required on every account, not nullable.
  • Anything past a per-account-type threshold renders visibly degraded — muted, flagged, whatever. Crypto goes stale in hours; a mortgage balance is fine for a month.
  • Aggregates inherit the worst staleness of their inputs. If one account is two months old, net worth is two months old and must say so.

That last rule is the one people skip and it's the one that matters. An aggregate is only as fresh as its stalest input, and quietly averaging fresh and stale data produces a number that's confidently wrong.

A dashboard that can lie to you is worse than no dashboard, because you'd have checked the real accounts otherwise.

Hard Part 2: Manual Entry Is Fine, Actually

I expected to need automated bank feeds. I mostly don't.

Balances that move slowly — 401(k), HSA, mortgage, brokerage — need updating monthly at most. That's a ten-minute ritual once a month, and the ritual has a genuine side benefit: you look at your accounts. An automated dashboard you never interact with becomes wallpaper.

Where automation actually earns its cost is anything that moves fast or has many rows: crypto prices, transaction-level spending. Those are miserable manually and cheap to automate.

So the rule I landed on: automate by rate of change, not by importance. Backwards from where I started, which was trying to automate the biggest accounts first — precisely the ones that need it least.

Hard Part 3: Definitions Are The Actual Product

Every metric hides a decision, and the commercial tools make those decisions for you silently.

  • Does "net worth" include your house? At what valuation?
  • Is a credit card balance you pay in full a liability, or noise?
  • Is a business expense that runs through a personal card part of burn? (My $215/month Claude Code line is a real burn item — I decided that deliberately and could defend either answer.)
  • Is "accessible" Roth contributions only, or the whole Roth?

There's no universally right answer. There's only your answer, applied consistently, written down.

This is the strongest argument for building it yourself, and it took me a while to see. It's not that the commercial dashboards compute badly. It's that they compute something precise according to a definition you never chose and can't inspect — and then you make decisions as though it were your number.

Build The Smallest Version

Don't build what I built. Build this:

  1. A table of accounts: name, balance, type, accessible (bool), last_updated.
  2. One view that sums them into net worth and shows the oldest last_updated next to it.
  3. A burn figure you type in manually from an actual expense audit.
  4. Runway = accessible ÷ burn. Days to FI = the gap ÷ savings rate.

That's a weekend, it's a spreadsheet if you want, and it delivers essentially the entire value. Everything I built beyond it has been refinement, and some of it was decoration I later deleted.

The point was never the software. It's that the definitions and the data are yours, and nobody can deprecate them.

GET_TRANSMISSIONS

Raw signal on finance, freedom, fitness, and tech. No spam. Unsubscribe anytime.

D
Dominic Baca

One engineer building Domdhi.OS in public — money, freedom, and the occasional 2am migration. Every number live, every commit public.

FOLLOW THE LOGS →
// NEXT IN THE LOGS