Strictly Spending · Pair-coded with Claude

A personal data tool for spending, pair-coded with Claude

Multi-bank CSV ingestion, rule-based categorization, recurring detection, and keyboard-driven triage. A local-first dashboard for discovering patterns in real household spending. Designed for power, built in the browser, owned end-to-end.


Claude

Coded it with me

Local

All data stays in the browser

4

Bank formats unified

Why I started

Off-the-shelf budgeting apps want bank credentials, push their own category taxonomy, and treat your data as theirs. None of that fits a household that wants to actually explore its own finances: by category, by merchant, by month, with the analytical lens you choose.

I wanted a dashboard built around one question: where is the money going, and what's worth changing? Powerful, private, local. The data never leaves the laptop. The interface gets out of the way.

The build, briefly

Pair-coded with Claude. Vite, React, TypeScript. MUI for components. Dexie wrapping IndexedDB. Zustand for filter state. MUI X Charts for the visualization. No server. No cloud.

Refresh the page and your data is still there. Open the app in a different browser and it's empty, because the data has never been anywhere else.

40 seconds of the actual app. Panel collapse, grouping toggles, category tooltip, Forecast, keyboard-driven Sort triage, drill into a month, isolate two categories for discovery, then back to year-to-date.

Or just try it

Launch the live demo

Loads in your browser with synthetic demo data preloaded. Nothing leaves your machine. Drop in your own CSVs to play, or clear the tab when you're done.

What I learned

The chart was easy. Categorization was the whole product.

I expected the chart to be the hard problem. It was the opposite. Different CSV exports tag categories their own way, or not at all. Getting one consistent taxonomy, then making it correctable in seconds, is what made the dashboard trustworthy.

The first version made you fix transactions one at a time with a pencil icon, which is where motivation went to die. The second version is a dedicated triage view that groups every uncategorized transaction by merchant, sorts the queue by dollar impact (biggest first), suggests the most likely category, and lets you commit each decision with one keystroke. Enter accepts the suggestion, 1–9 pick from the grid, ⌘Z undoes. Going from 700 uncategorized rows to zero takes about three minutes, and it feels good.

The Sort view. A card for "Demo Property Mgmt Rent" shows 5 occurrences totaling $9,750 with a Monthly recurrence chip and three recent transactions. The suggested category Housing is highlighted on the right; below, a numbered grid of colored category buttons offers Housing (1), Groceries (2), Restaurants (3), Transportation (4), Auto Loan (5), Utilities (6), Subscriptions (7), Mortgage (8), Student Loans (9). The nav bar shows the Sort tab with a 45 badge. The progress bar reads "8 merchants left, 0 sorted."

The Sort view. One decision categorizes every transaction from a merchant at once, and optionally saves a rule so future imports catch the same pattern.

The floor versus the discretionary.

Once recurring charges (rent, utilities, subscriptions, the gym) are detected and pinned, the rest of the spend reads completely differently. You can finally separate the floor (what you owe) from the discretionary (what you choose). That distinction is the entire game.

The Forecast tab. It projects next month's spending at $4,750, broken into $2,802 recurring (rent, auto loan, utilities, insurance) and $1,948 in per-category budgets. Each line has a toggle switch.

Forecast tab. Recurring charges separated from variable budgets, each line individually toggleable.

What Claude was good at, and what it wasn't

Strongest at sketching tradeoffs and writing the boring code fast. Weakest when it over-engineered (a three-tier abstraction when I wanted a 12-line function). The fix was on me: give more specific direction, push back, redo it.

The working dynamic landed on I direct, Claude implements, I review. Plain, but it's what stuck.

"An afternoon of pair-coding produced what I'd been failing to build on my own."

What's in there

Sort view: keyboard-first triage

Uncategorized transactions group by merchant, sort by dollar impact, and surface one card at a time with a suggested category pre-selected. Enter accepts, 19 override, ⌘Z undoes. One decision categorizes every transaction from that merchant, and optionally saves a rule for future imports.

Watch folder + content-hash dedup

Point the app at a folder. Drop in a CSV at the root, or in any subfolder up to five levels deep. The scanner reads it, hashes the content, and dedups against everything already imported. The same statement re-downloaded under a different name gets skipped.

The Settings page. It shows a Watch folder section with a Connect folder button, a Demo data section showing 217 demo transactions loaded, and a Demo mode toggle currently turned on.

Settings: Watch folder, Demo data, and Demo mode.

Custom chart tooltip

The default tooltip sorted categories by stack order, with no total. A custom renderer sorts them by dollar value and adds a Total row. Every hover answers "what dominated this month?" at a glance.

A chart tooltip hovering over March's bar. It shows Housing $1,950, Travel $850, Shopping $537, Groceries $511, Auto Loan $389, and so on down to Entertainment $30, with a Total row reading $5,060.

Categories ordered by dollar value, total at the bottom.

JSON backup and restore

The data lives in IndexedDB. "Clear site data" would wipe it. One click exports the whole app state to a JSON file. Drop it back to restore.

Demo mode

A runtime filter for synthetic data. I added it to screenshot the app without exposing real finances. It stayed in for screen-share calls and anyone who clones the repo.

Discovery, on my own terms

The strapline at the top of every screen reads "Where is the money actually going?" This is the tool that answers it. Visually, locally, and shaped to how my household actually thinks about money.

Bank CSVs in. A stacked-bar visualization out. Recurring detected, budgets forecasted, uncategorized triaged in keystrokes. Designed and pair-coded with Claude across many sessions. The model does the typing. I do the directing.

Building this way?

If you're shipping local-first tools, designing with AI as your engineering partner, or just curious about the workflow, let's talk. The code is on GitHub. MIT-licensed, no warranties, fork freely.