Work / 2026 / web
FinanceFlow
Self-hosted personal finance tracker that forecasts instead of just recording.
- Status
- building
- Stack
- Next.js 16 · TypeScript · React 19 · Tailwind CSS 4 · SQLite (sql.js) · Recharts
- Database
- sql.js — pure JS, zero native deps
- Forecast
- Regression + WMA + seasonal, 90% CI
- Anomalies
- Flagged beyond 2σ from history
- Data leaves the machine
- Never
Income and expense tracking across 25 categories, budget planning, savings goals with risk buffers, and statistical forecasting — linear regression, weighted moving averages and seasonal adjustment with 90% confidence intervals. Runs entirely on a local SQLite file with no native dependencies.
The problem
Every budgeting app is a subscription that wants a bank login. The interesting question is not “what did I spend last month” — a spreadsheet answers that. It is “given how I have actually behaved for the last two years, what is the range of outcomes for the next six months, and how confident should I be in it.” That is a statistics problem wearing a personal finance costume.
Constraints
- Financial data does not leave the machine. No cloud, no sync, no vendor.
- Must be trivially self-hostable, including on hardware where compiling a native SQLite binding is a bad afternoon.
- Forecasts must state their uncertainty. A point estimate with no interval is a lie told confidently.
Decisions
sql.js instead of better-sqlite3. The native driver is faster and it is the obvious pick. It also needs a toolchain on every machine that runs the app, which is precisely the friction that stops a self-hosted tool from being self-hosted. Compiling SQLite to WebAssembly costs performance the dataset is far too small to notice.
Three forecasting methods, not one. Linear regression catches the trend, weighted moving averages track recent behaviour, and seasonal adjustment handles the fact that December is not March. Each is weak alone. Reporting a 90% confidence interval rather than a single number is the part that makes the output honest.
Anomaly detection at two standard deviations. Not a machine learning model — a threshold with a stated meaning. When it flags a month, the reason is one sentence long and checkable by hand.
Savings goals carry a risk buffer. Conservative, moderate and aggressive are not aesthetic labels; they change the buffer applied to the projection. Planning a purchase against the mean is how the plan fails.
Tradeoffs
Local-only means no phone access without exposing the machine, which is the next problem and the reason the homelab exists. A single-file database means no concurrent writers, which is fine for one person and would be a design error the moment it were not.