Moneh: Personal Finance Tracker & API Gateway
A self-hosted personal finance system for a two-person household: a mobile-first SvelteKit app for logging expenses in under 10 seconds, backed by a Fastify API gateway that dual-writes every transaction to Supabase and the Actual Budget ledger with idempotency and automatic reconciliation. It also suggests next month's budget from recent spending and assigns it automatically at the start of each month.
Tech Stack
Overview
Moneh is a personal expense tracker built for private use by my spouse and me. It is split into two services: tracker-moneh, a SvelteKit web app optimized for fast expense entry on phone and desktop, and moneh-gateway, a Fastify API gateway that owns all business logic. Supabase PostgreSQL is the operational store, Actual Budget is the financial system of record, and Google Sheets is kept as a reporting layer for monthly reviews.
Challenges/Problems
- Two sources of truth: Every expense has to land in both Supabase and the Actual Budget ledger. A network failure between the two writes must never leave a duplicate or a silently missing transaction.
- Speed of entry: If logging an expense takes longer than a few seconds, it doesn’t get logged. The app had to be faster than writing it down.
- Budgeting by hand: Setting each category’s budget every month was tedious and easy to forget, especially with credit card and paylater bills landing in the following month.
- Security: Database keys and ledger credentials must not be exposed to the browser, and each user must only ever see their own data.
Solutions
- API Gateway: All traffic goes through a Fastify gateway that holds the credentials, authenticates with HTTP-only session cookies, and calls Supabase with the user’s own session so Row Level Security always applies.
- Saga Dual-Write: Expenses are written with a client-generated idempotency key and move through a state machine (
PENDING→SYNCED, orROLLBACK_PENDING→SYNC_FAILED). A reconciliation engine matches pending records against the ledger using correlation IDs embedded in transaction notes. - Rapid Capture UI: A one-tap sheet with a large amount input, category and payment-method chips, payee-based autofill, and an Undo toast.
- Automated Budget: Next month’s budget is suggested per category from recent spending (with fixed and manual modes and an income cap). A once-a-day run on first app open saves the suggestion on the 28th and auto-assigns it on the 1st, using a compare-and-set claim so concurrent tabs can’t run it twice.
- Spending Insights: Monthly summaries, daily spending trends, category and payment-method breakdowns, a “why is this category high” explanation, and automatic adjustment of next month’s Bills budget for credit card purchases.
- Multi-User, Multi-Budget: One gateway serves several users, each linked to their own Actual Budget file.
Key Impact
- Reliable Ledger Sync: Idempotency plus reconciliation keeps Supabase and Actual Budget consistent without manual cleanup.
- Fast Daily Use: Expenses are logged in seconds from a phone, so tracking actually happens.
- Hands-Off Budgeting: The monthly budget is planned and assigned automatically, while categories the user sets manually are never overwritten.
- Self-Hosted: Both services run as Docker containers on a personal server.