Finance Owl
A personal finance app — bank sync, budgets, investments — across web and mobile, where the AI features are optional and can run on a local model.

The constraint
Finance apps want your bank login and then send your transactions to a model you did not choose. The useful parts — a budget, a categorised ledger, an investment view — do not need either compromise.
The approach
A NestJS API with Drizzle on Postgres, a SvelteKit web app and an Expo mobile app over the same API. Plaid handles bank sync; a rules-based categorizer runs before any model is asked; and the AI layer can point at a local Ollama model or be switched off.
- 1Rules before models
Put a deterministic categorizer in front of the AI, so most transactions never reach a model at all.
- 2Make payments idempotent
Made the Stripe webhook safe to receive twice, because webhooks are delivered at least once.
- 3Keep secrets local
Rendered the TOTP enrolment QR code on the server instead of sending the secret to an image service.
Outcomes
- Rules-based categorisation first, AI only for what the rules cannot place
- Passkeys and TOTP, with the 2FA QR code rendered locally rather than by a third party
- An idempotent Stripe webhook and a real job scheduler
- One pricing source instead of prices restated across the app
Building a personal finance app with a NestJS API, SvelteKit web and Expo mobile clients, Plaid sync, passkeys, and an optional local-model AI layer.
Related projects
- Read
Verso
A diary for artworks — Letterboxd where the unit is an individual work, not a visit. Offline-first capture over a real catalogue of 10,000 works currently on view at The Met.
- Read
Talker
An open source teaching assistant, built as a USC master's capstone, that drafts answers to course-forum questions from the lecture notes, with hybrid retrieval, a reranker, and an evaluation harness that scores its own retrieval.
- Read
Tidy Roll
A Tinder-swipe interface for cleaning up your camera roll. Swipe right to keep, left to toss, watch the megabytes tick up. Free, no ads, no accounts, entirely on-device.