finance.mikkelmanniche.dk
My own finance app. It pulls transactions straight from my two banks through open banking and shows budget, savings, subscriptions and investments. The video was recorded with demo data.
Why I built it
Ready-made budget apps show an overview, but you can't ask questions about the numbers yourself or fix the logic that decides what a transaction is. I wanted raw data in my own database, categorisation I can adjust myself, and a way to ask questions about the numbers.
What it does
Every morning a job syncs the accounts, fetches exchange rates and share prices, and keeps track of when the bank's consent for data access needs renewing.
The morning job7 steps · fixed order
- Exchange rates from the ECB first, so euro transactions get today's rate straight away
- Share prices for every holding and everything on the watchlist
- Sync of all accounts new transactions from both banks, no duplicates
- Consent notice a message before the bank's MitID consent for data access expires
- Alerts double charges, unusually large amounts and fees
- Month-end close once a pay period ends, it's settled once
- Weekly email Sundays only: the week's numbers in five lines
If one step fails, the others still run. Notifications arrive as a push notification, otherwise by email.
There's a budget, savings goals linked to accounts with an expected date, a return curve for investments and a figure for what's available once fixed expenses and planned savings are deducted. Possible double charges and unusually large expenses arrive as a push notification on the phone, and each pay period is settled once it ends.
Categorisation
Categorisation follows fixed rules, in a set order:
Transfers between my own accounts are recognised, so they don't count as expenses twice. Receipts can be added as a photo.
The bank's raw text is translated into a real name — the raw text can still be seen in the details
- Card purchase and terminal number removed:
MCD 03942 - Lower case, punctuation becomes spaces:
lime krsel 33go - Recognised among known shops
Ask your numbers
The numbers can be queried in a chat in the app and through an MCP server, so an AI assistant answers from the actual transactions instead of guessing.
Do I have two transactions from the same place on the same day?
Calling soeg_posteringer ·
Yes, once: two Lime rides on the same day. The bank's texts are different, so these are two real rides, not the same transaction counted twice.
The answer is based on the transactions the tool found.The chat and the MCP server share the same 12 tools:
- maanedsoversigtMonthly overview
- historikMonthly history
- soeg_posteringerSearch transactions
- saldiBalances
- til_raadighedAvailable funds
- budgetstatusBudget status
- abonnementerSubscriptions
- opsparingsmaalSavings goals
- personerPeople
- investeringerInvestments
- kategorierCategories
- saet_kategoriSet category
The technology
Next.js and React with a SQLite database hosted by Turso, and Drizzle to keep the database structure and the code in sync. The bank connection runs through Enable Banking, an approved provider of open banking access. The layout builds on Jakob Fisker's component library "Fisker Finance".
The journey of a transaction
- The banktwo banks, own accounts
- Enable Bankingopen banking with MitID consent
- TursoSQLite + Drizzle
- The appNext.js + React, chat and MCP
Tested against the real numbers
The calculations behind budget and spending existed in two versions, one in the code and one in the database. When they were merged into one, the result was run against the whole database before the change went live. All the numbers on the analysis and budget pages matched, apart from five zero-kroner transactions that fell out of a count.
A performance review brought the number of database lookups down:
Database lookups on the front page
46→46
Database lookups on the analysis page
61→61
The main lesson: categorisation from the banks' free text requires ongoing verification against real data. Several errors only surfaced once the numbers were reviewed systematically.