Selected work · 06
Haushalt — Personal Finance Tracker
A local budgeting app that replaced a set of spreadsheets, with linked money pots, automatic capital-gains tax handling and a one-click desktop launcher.
Highlights
What shipped
- Replaced a set of monthly budget spreadsheets with a FastAPI and SQLite backend and a single-page React front end.
- Modelled the money flow as linked ledgers, so every sale, purchase or trip updates the right balance automatically and stays in sync on every edit or deletion.
- Computed net trading profit under the German flat tax on capital gains, and split each profit between paying down past losses and spendable money.
- Imported the historical spreadsheets with a dedicated script, and added CSV and Excel export for backups or a tax advisor.
- Covered the money rules with a pytest suite that runs on every push through GitHub Actions.
The story
Behind the build
Overview
I built Haushalt for myself, to replace the Excel sheets I used to run my monthly budget. The spreadsheets worked until the money started moving between them: income from several sources, purchases paid from one pot of money, trips, savings goals and trading results, each tracked in a different place and reconciled by hand. Haushalt puts all of it in one model, so one change updates everything that depends on it.
It runs on my own machine, with no accounts and no cloud. A small macOS launcher starts the backend if needed and opens the app in the browser, so using it feels like opening a desktop program.
Budget months
Each month holds income and expense entries in a fixed set of categories carried over from the original spreadsheet, and the API rejects anything outside that set. Fixed monthly items are stored once as recurring templates. Rolling over to a new month creates it with those items already filled in, without duplicating any that were added by hand. The month view shows the totals and what is left, and a statistics view adds category totals, monthly trends and average income and spending, averaged only over the months that actually have data.
Money pots and linked ledgers
At the end of each month, I split the leftover between two pots: savings and personal money. The personal pot is the money I can actually spend, so most other features flow in or out of it. Extra income is deposited into it automatically, and purchases and trip expenses are withdrawn from it. Every transaction carries a category, so each pot shows where its money came from and what it was spent on.
The important design choice is that these links are kept by the backend, not by me. Recording a sale creates the matching deposit. Editing the sale updates it, and deleting it removes it. Deleting a purchase refunds it. If the personal pot runs low or goes below zero, every relevant response carries an alert, and the shortfall is shown as debt rather than hidden.
Income paid in pounds or dollars is converted to euros with a default rate, which can be overridden with the exact rate from the payment receipt. Trips group their own expenses by type, such as transport, accommodation and food, while still rolling up into the personal pot as one travel category.
Trading and tax
For trading, I enter the gross profit, and the app computes the net amount under the German flat tax on capital gains: 25% capital gains tax plus the 5.5% solidarity surcharge on it, with no church tax. Each net profit is then split. One part counts against previously recorded losses, and the other is deposited into the personal pot as spendable money. The split is a per-entry setting and is recomputed whenever the profit is edited.
The loss list is deliberately kept apart from the pots. It is pure bookkeeping, showing the losses incurred, how much has been covered by later profits and what is still outstanding, and it never changes the money that is actually available. Dividends follow the same rules, and overviews break results down by year, month and account.
Wishlist, parcels and sharing
A wishlist tracks things I want to buy, with images, categories and how much I have already set aside for each. Items can be reordered by drag and drop and are archived once bought. The wishlist can also be shared as a read-only gift list through a private link with an unguessable token. A parcels page tracks orders by their tracking number and links each parcel to the wishlist items it contains.
Engineering
The backend is FastAPI with SQLAlchemy models and Pydantic schemas over SQLite. The database evolves through small, idempotent migrations that run on startup and only add what is missing, so existing data is never rebuilt. The front end is a single-file React app with German number and date formatting. It started with in-browser compilation and now ships precompiled by a small Babel build script, which removed a noticeable delay on every load.
Data safety was a requirement from the start, because this is my real financial history. The full database can be downloaded as a backup, and every dataset exports to CSV or Excel in a flat layout that an importer can read back. Tests cover the budget rules, rollover, pots, extra income, shopping and travel, trading and exports, and run on every push.
Keep exploring
More projects
Cross-Lingual RAG Evaluation
A controlled study of how much retrieval-augmented generation degrades when questions and documents are in different languages, and which fix closes the gap.
qado.ai IDP: RAG and AI Agents for Procurement
My interdisciplinary project at the AI startup qado.ai: a modular RAG pipeline over contract data, a benchmark for its retrieval quality, and prototype agents for strategic purchasing.
Blog Studio
A web app that turns SEO keywords into source-grounded B2B blog posts in English and German, with a human review step at every stage.
Job Hunt
A local job-search dashboard that writes tailored CVs, cover letters and application emails, and refuses to claim anything the applicant's own CV does not support.
Application Optimizer
A command-line pipeline that scores job fit, tailors a LaTeX CV towards a posting's keywords, and writes a matching cover letter, delivered as two finished PDFs.
Legacy Data Migration Platform
A relational data platform consolidating historically grown legacy records into a clean target structure, with a Dash front end and REST API for exploration.
Machine Learning Pipeline
A supervised and unsupervised modelling pipeline in Python, covering feature engineering, hyperparameter tuning, and cross-validated evaluation.
In design
Automated Trading System
The design for an automated swing-trading system on Interactive Brokers, built around separate processes, shared backtest and live code, and safety rules that must exist before any real order.
Questions?