Personal Finance Tracker
No backend, no account, and no fetch() call to anywhere but Hugging Face — once, on request.
What it does
Import a statement, get it categorized, keep it local
Transactions come in by manual entry or by importing a bank statement — CSV, Excel, OFX, or PDF, parsed off the main thread in a Web Worker. Every transaction runs through a categorization pipeline and lands in IndexedDB. There's no server: the whole app is a static bundle, works offline as an installable PWA, and — verified directly in the source, not just claimed in the README — there is not one fetch or axios call anywhere in the codebase.
Architecture
Rules do the work; a local model only covers the gaps
Import
CSV / XLS / OFX / PDF parsed in a Web Worker. Repeat imports from a known bank auto-map columns from a remembered profile.
Normalize
Strip bank noise, detect the payment channel (UPI/NEFT/IMPS/ATM/etc.) from the description text.
Rule engine
User rules first (always win), then ~98 precompiled system rules by priority tier — structural overrides, income signals, keyword categories. Compiled once, not per row.
Hugging Face CDN · third-party
Opt-in only. The one real network call in the app — downloads the 22MB MiniLM model once, then it's cached by the browser for every session after.
On-device embedding model
A real MiniLM sentence-transformer (transformers.js, ONNX/WASM) runs in a Web Worker, compares the description against 10 category prototypes by cosine similarity.
IndexedDB
Versioned schema (v1 → v5), a dedicated store per data type. The AI suggestion is surfaced, never auto-saved — the user confirms it.
Worth being precise about
What 'on-device AI' actually means here
The rule engine handles the overwhelming majority of rows with zero ML involved — it's the default and only thing that runs unless the user opts into the AI feature. What's genuinely there: a real 22MB sentence-embedding model from Hugging Face, cached after the first download, matching uncategorized transactions against ten category prototypes by cosine similarity — not a fine-tuned classifier or a hosted LLM call. Confirmed transactions are remembered too, so recurring merchants stop needing the model at all.
"Anomaly detection" and forecasting elsewhere in the app are plain statistics — a Z-score against a rolling baseline, linear extrapolation — not AI, despite living under the same menu.