Skip to content
brorn
No. 008 · Personal life

money.me

One statement that brings accounts from several banks (personal and business) into a single dashboard, pulled automatically via Open Banking.

In production
Period
2026-09 → now
Platforms
Web
Role
Solo: design, build, ship
Tech
Fig. 1 · Unified statement
Fig. 2 · Recurring bills
Fig. 3 · Connections and rules

§1The problem

Statements were scattered across different banking apps, each in its own format, and none showed the whole picture. I needed to see everything together, categorised, and know which recurring bills of the month were already paid.

§2What I built

  • Bank connectionReal connection to banks through the Enable Banking API (Open Banking), with bank consent and automatic daily sync.
  • Unified statementFiltered by sub-account (the app's unit is the sub-account, not the bank).
  • CategorisationLearns rules from the corrections the user makes.
  • Recurring billsExpected amount, “paid or not” detected from the statement, provisioning per “pocket” (reserve sub-account), monthly/bimonthly/four-monthly periods, multiple currencies with ECB rates.
  • One-off importPayments brought in once from another of my apps, as a copy, so this app doesn't depend on it.
  • Demo modeSample data (fixtures), without touching any bank.

§3The hard parts

5 entries
  1. 01

    Real Open Banking API integration

    Consent, HTTPS-only redirects, the bank's daily query limit, and transient errors that the next sync clears.

  2. 02

    Deduplication

    Syncing again never duplicates transactions.

  3. 03

    Detecting a paid recurring bill

    Even when the bank's text doesn't match the name, by also using amount and a window of days.

  4. 04

    Modelling sub-accounts and dates

    Pocket name and account type come from different endpoints; the transaction date is used instead of the booking date.

  5. 05

    SQLite schema migrations without data loss

    For example, rebuilding period constraints.

§4Result

transactions in the first import
1,000+
inserted by the second sync (no duplicates)
0

Running in production since September 2026, with several real bank connections and automatic daily sync. The first import brought in over a thousand transactions, and a second sync inserted zero (deduplication working).

§5Stack

  • Next.js 16
  • React 19
  • TypeScript 7
  • Tailwind 4
  • SQLite (better-sqlite3)
  • Own design system
  • Enable Banking (Open Banking / PSD2)
  • pm2
  • Daily scheduling
  • Tailscale