Own productPrivate
Invoices in, reconciled books out
Our own property finance system. Claude reads invoices into a validated ledger, and the site refuses to build if the books don't add up.
- Industry
- Property and finance
- What it shows
- AI document extraction, Finance dashboards, Data quality
- Year
- 2026
- Status
- Private
In numbers
- source documents archived, each with a fingerprint
- 47
- ledger line items booked from those documents
- 207
- validator checks the books must pass before the site builds
- 52
- kinds of planted mistake the self-test proves are caught
- 8
Figures come from the project’s own files and records.
What changes
The steps people did by hand, and the route the work takes now.
A supplier invoice arrives
Before
- Open the PDF
- Retype every line into the ledger
- File the original
- Check the totals at month end
With AI
- Claude reads it and books every line
- A validator and build gate check the books
Books reconcile, every entry traceable
The problem
A small holding company with two flats and a parking space still produces a steady stream of paperwork: purchase and renovation invoices, rent, maintenance, and tax at the end of the year. Spreadsheets drift, receipts go missing, and the question “what did this property actually earn?” takes an afternoon to answer.
What we built
A private finance system with a dashboard for income, expenses, rent status, maintenance and the tax summary, plus a bookkeeping workflow behind it. Invoices go into an inbox. Claude, following a written bookkeeping procedure, reads each one, books every line into the ledger and files the original with a fingerprint so it can be traced later.
AI where it helps, rules where it matters
The AI does the tedious part: reading documents in any layout and typing them up. It does not get the final word. Every booking passes a validator, a self-test proves the validator still works, and the build stops if anything fails. Money is summed in whole cents, so rounding can’t creep in.
There are no AI calls at runtime. The dashboard only shows data that has already passed the checks.
Inside the checks
Open the system map of every part, follow one dummy invoice from the inbox to the dashboard, open the validator’s eight groups, or run the self-test that plants mistakes to prove they are caught.
Interactive system map
Every part of Finance Hub, and how they connect
29 parts and 8 journeys, from a document in the inbox to the dashboard, the checks and the backups. Checked against the code on 12 October 2026.
Play 8 journeys, or click any of its 29 parts.
- checks the books must pass
- 52
- self-test cases: a clean copy and 8 planted mistakes
- 9
- source documents archived, each with a SHA-256
- 47
Inbox
- Invoices and receipts all go to one folder.
- PDFs, photos and scans are all fine.
Intake
Claude reads
- Book what was actually paid, gross.
- Mark cash only when the document says so.
- Payer unknown: book it as TBC and ask.
- Corrections are new rows or status changes, never deletions.
- Wall paint, 10 l × 249.00 + 10.29 = 59.29
- Primer, 5 l18.00 + 3.78 = 21.78
- Brush and roller set12.00 + 2.52 = 14.52
- Masking tape × 410.00 + 2.10 = 12.10
- Invoice, net + VAT = total89.00 + 18.69 = 107.69
Archive
- Comes from the inboxArchive accepts inbox files only.
- Name follows the patternYYYY-MM-DD_supplier_docnumber_subject_property.ext2026-09-17_supplier-a_A-0917_paint_flat-a.pdf
- Content not archived beforeAlready archived content is refused.
- Copy re-hashedThe copy’s SHA-256 equals the original’s, so it is byte-identical.9f2c4b7e…a4c7e41a=9f2c4b7e…a4c7e41a
- Inbox file movedTo _processed/2026-09-17/, kept, never deleted.
Validate
- Daily backups, kept 30 days.
- CSV shape
- IDs
- Expense rows
- Mirror and seed
- Line items
- Document store
- Assets
- Ledger
Build gate
- When books files are staged, a pre-commit hook refuses unstaged edits and runs the checks again.
- 1LintPass
- 2Books check · 52 checksPass
- 3Self-test · 9 casesPass
- 4Server testsPass
- 5Unit testsPass
- 6BuildPass
- 7Dist checkFails the build if any of 6 leak patterns appear in the public bundle: line-item IDs, the unit cost field, books row IDs or invoice numbers.0 found
Dashboard
- Saves carry a revision token. A stale save gets a conflict, and the person chooses Discard mine or Merge.
- A guard refuses any save that would make a stored record disappear. Deletes are soft.
- The previous state is copied before every overwrite. The audit log is append-only, and deleted items can be restored.
1CSV shapeColumns and row widths
- Each file has the expected number of columns
- Every row is as wide as the header
2IDsUnique, well formed, no gaps
- IDs are unique
- IDs are well formed
- No gaps in the sequence
3Expense rowsNet + VAT = total, splits add up1 self-test case
- Dates are ISO, YYYY-MM-DD
- The property is a valid one
- Net + VAT = total
- Net and VAT are both present or both blank
- The split across assets adds up to the total
- A non-cash row has a source document
- Fields with a fixed list hold a value from it
The self-test plants here: a typo in a value from a fixed list.4Mirror and seedApp rows tie to the books5 self-test cases
- App rows tie to the books
- The grand total ties
- Each row sits on the right asset
- Amounts match, within 1 cent on odd splits
- Dates match
- Categories match
- A locked owner decision is enforced
The self-test plants here: a cost booked to the wrong flat in the app mirror; a 50/50 split shifted; a stale seed; a cost moved to the wrong flat column in the CSV; a locked owner decision broken.5Line itemsDerived from the CSV, no hand edits1 self-test case
- The JSON is exactly derived from the CSV, with no hand edits
- Invoice and quantity match
- Discount arithmetic is right
- Each document’s lines sum to its total
The self-test plants here: a hand-edited line-items file.6Document storeSHA-256 matches, append-only1 self-test case
- Status is an allowed value
- The file exists
- Its SHA-256 matches the register
- No two files share the same content
- No unregistered files
- Superseded copies are marked
- Originals are append-only, checked against git
- Every source document resolves to a file
The self-test plants here: one byte appended to an original.7AssetsEquipment ties to its invoice
- Equipment net amounts sum to their invoice
- Serial numbers are unique
8LedgerStated total equals computed
- The header date is not older than the newest change
- The stated grand total equals the computed one
Does the validator still catch mistakes?
- 1Nothing planted: a clean copyAll groups passWaitingRunningPasses
- 2A cost booked to the wrong flat in the app mirrorCaught by Mirror and seedWaitingRunningCaught
- 3A 50/50 split shiftedCaught by Mirror and seedWaitingRunningCaught
- 4A hand-edited line-items fileCaught by Line itemsWaitingRunningCaught
- 5One byte appended to an originalCaught by Document storeWaitingRunningCaught
- 6A stale seedCaught by Mirror and seedWaitingRunningCaught
- 7A cost moved to the wrong flat column in the CSVCaught by Mirror and seedWaitingRunningCaught
- 8A locked owner decision brokenCaught by Mirror and seedWaitingRunningCaught
- 9A typo in a value from a fixed listCaught by Expense rowsWaitingRunningCaught
What it shows
Most finance teams have the same problem at larger scale: documents arrive in every format, someone retypes them, and errors surface at month end. The pattern here, AI extraction behind strict validation and a clear audit trail, carries straight over to accounts payable, expense claims and supplier onboarding.
Under the hood
- Claude skill
- React
- Vite
- Netlify Functions
- Netlify Blobs
- recharts
01Inbox
Invoices and receipts land in one folder, in any format. Intake fingerprints each file and sorts it as new, a duplicate or a re-scan before anything is read.
02Claude reads
A Claude skill extracts supplier, dates, VAT and every line item into the ledger, and archives the original with a fingerprint.
03Validation
52 checks in eight groups, from net plus VAT equalling the total to every original matching its SHA-256. A self-test plants eight kinds of mistake in a copy of the books to prove each one is caught.
04Build gate
The site will not build if the books fail, or if any bookkeeping data would leak into the public code.
05App
A dashboard for income, expenses, rent, maintenance and tax. Saves are checked for conflicts, and nothing is ever silently deleted.
06Backups
A scheduled job keeps a daily copy of the app for 30 days, every save keeps the previous state first, and the books get an add-only off-site copy.