Work / case study 03

Budgy

Household budgeting for couples. One shared ledger, as little bookkeeping as possible.

Role
Sole builder — product, design system, schema, encryption, infrastructure, operations
Year
2026
Status
Running in production
Live product: link pendingSource repository: link pending
  • 1,127unit tests passing
  • 54database migrations
  • 3member roles enforced in the database
  • 1ingestion path for bank, CSV and manual rows
A composition built from Budgy's design tokens showing a month-at-a-glance card with a left-to-spend figure, a stacked category bar in the eight household hues, plan-versus-actual bars, a shared ledger with per-partner avatars and a contributions split. Illustrative numbers, not a product screenshot.

The problem

Two people share money but not a view of it. Statements sit in two bank apps, categorising is manual, and “who paid what” turns into a conversation nobody wants to start. Budgy gives a household one ledger that fills itself in from the banks, a plan it can keep, and a monthly recap both partners actually look at.

Product decisions

  • Time to value is the metric. The onboarding is designed so the person setting up sees their own plan in under 90 seconds, and an invited partner is inside the shared budget in under 60, with nothing to configure.
  • One ingestion path. Bank sync over PSD2, CSV and XML imports of Finnish bank formats and manual rows all go through the same pipeline: identity, rules, suggestions, monthly facts, duplicate links. Everything downstream behaves the same regardless of source.
  • Budgets are plans, not copied numbers. A budget line is effective-dated with a cadence and an optional rollover, and the database resolves it per month. Nobody types the same number twelve times.
  • Who paid, without a debt ledger. Payer attribution comes from bank-account ownership for synced rows. Contributions are shown as information, not as a settle-up. It is a household, not a tab.
  • An assistant that never invents a number. Ask Budgy answers from tool calls over the same access-checked reads the interface uses, behind an explicit consent gate, with a privacy mode that hands the model merchant pseudonyms. Writes only ever land as proposals a person approves.
  • A design system built for the kitchen table. Warm neutrals, one accent, money set in tabular figures through a single component, thumb-first on phones and dense on desktop, with a reduced-motion switch. The chrome recedes; the household’s numbers carry the room.

Architecture

Next.js 16 App Router on Vercel with Supabase Postgres. Multi-tenancy is enforced in the database: row-level security with owner, editor and viewer roles, and a typed repository seam that is the only path to privileged access.

Personal data is ciphertext at rest. Each household has its own data key, wrapped by a key-encryption key from the environment; fields are AES-GCM with the row identity as associated data, so a value cannot be copied between rows or households; equality lookups go through blind indexes; key rotation resumes if it is interrupted.

The AI layer is provider-agnostic with a fallback chain and prompt caching. An MCP server with its own OAuth 2.1 authorization server lets external AI clients connect per person, with per-household consent, and read the same tools the assistant uses.

Ownership

I ran a full architecture review against the first version and closed every finding: write authorization moved into row-level security, multi-step mutations became atomic Postgres functions, all money math moved into pure, tested modules, and CI started gating every pull request with lint, typecheck, unit tests, a real-database suite and a build. The product, the design system, the schema, the encryption, the infrastructure and the operations are all mine.

What I would do next

Realtime updates between partners on the same ledger, trip budgets that span a date range instead of a month, and the cross-budget home view that makes several budgets feel like one place.