Abdalla Bakr
All projects
In progress

Personal Finance Tracker

A self-hosted finance tracker built as a university group project. My piece was the natural-language assistant that turns plain questions into safe filters over your own data, so the model never sees raw rows.

Python Flask SQLite Bootstrap 5 Anthropic

What this is

FinTrack is a personal finance web app: you register, add your accounts, categorise income and expenses, log transactions, and get a dashboard with balance, monthly totals, and an expenses-by-category chart. Everything sits in a local SQLite file. No bank integration, no cloud sync, no subscriptions. We treated local-only as a feature, not a limitation.

It was a team build for a university software-engineering module (SWE5303), where the assessment weights the requirements document as heavily as the demo. I was the lead contributor across the codebase, and the part I owned end-to-end was the assistant that sits on the side of the screen.

The part I built: an assistant that never sees your data

You can ask the assistant things like “how much did I spend on fun stuff last month?” and the model never touches your transactions. It sees the shape of your data (what accounts exist, what categories you’ve made, what date ranges are available) and returns a small structured intent: which categories, which account, which period, a few description keywords. The app reads that intent and builds the SQL itself, with parameters.

Putting a language model directly in front of a database is the easy version of this idea and the one that fails slowly. The model writes a query, the database runs it, and a year later a confidently wrong join has rewritten half someone’s ledger. So I split the responsibility: the model decides the what, the application decides the how. The worst the model can do is ask for something that doesn’t exist, which is a small UX problem rather than a data problem.

That pattern (intent in, never SQL) became the most interesting thing in the project, and it generalises to almost any AI feature that sits in front of structured data.

What I learned building it

Treat the model as untrusted, even in a single-user app. Every piece of model output crosses a validation step on the way in. An invalid request degrades to a clear message instead of a bad query. The discipline costs almost nothing; skipping it costs you at the worst possible time.

Make it work without a key. The assistant parses the common questions locally by default and only calls a model when an API key is set. That keeps the demo reproducible on any laptop, handles vague wording and typos through the local path, and means the AI is an upgrade rather than a dependency.

Categories are where finance apps quietly fail. They either ask every time or guess badly. The app proposes a category from the description and the user one-clicks to accept or override; rejected suggestions shape the next guess, so it improves without anyone training a model.

How it’s built

Python and Flask on the server, SQLite in a single file, Flask-Login and Werkzeug for auth, Bootstrap 5 and Chart.js for the interface. Schema changes are versioned in plain migration scripts so the history lives in the repo. The team handled accounts, transactions, categories, the dashboard, onboarding, and the auth redesign; I handled the assistant and its filter validator.

Status

In active development. Accounts, transactions, categories, and the dashboard work end-to-end against a local database. The assistant runs behind a feature flag while I finish hardening the filter validator. The repository is private for now; a live link will land here once the public version is ready.