Private source

Kill Bills

Personal and family finance on a serverless stack: bank statements and receipts parsed into one ledger, across web and mobile.

Core stack
  • Next.js
  • Expo
  • TypeScript
  • Python
  • Firebase
  • Document AI
Source access

Source is private.

Chapter 01

Overview

A household ledger that gets its data from the artefacts you already have — bank statement exports and photographed receipts — rather than from typing every transaction in. Statements are parsed by a registry of per-bank strategies; receipts go through OCR. The interesting constraint is that neither is trusted: automation only ever writes a transaction as DRAFT, and only a human action in the UI promotes one to ACTIVE. A parser that misreads a column cannot quietly corrupt the ledger. Imports carry a hash so re-importing the same statement is idempotent rather than duplicating months of history. It is a pnpm monorepo — a Next.js web app, an Expo mobile app and Python serverless functions — with every domain type defined once in a shared package that all three consume.

Chapter 02

Highlights

  • Automation writes DRAFT only; promotion to ACTIVE is a human action, so a misparsed statement cannot corrupt the ledger
  • Per-bank statement parsers behind a Strategy interface and a Factory registry, so a new bank is one class rather than a new branch in a parser
  • OCR behind the same pattern, letting Cloud Vision and Document AI be swapped without touching calling code
  • Idempotent imports: every transaction carries an import_hash, so re-importing a statement is a no-op
  • Client queries deliberately avoid composite indexes — setup is console-only, so an index-requiring query would fail at runtime for anyone who never deployed one
  • One shared package defines every domain type and Firestore converter for web, mobile and the Python API
  • English, Hebrew and French with full right-to-left layout