Valox Invoice
A self-hosted invoicing tool that issues compliant bilingual invoices and fails loudly
- Role
- Solo, directing agents
- Status
- Shipped
- Source
- Private repository
- Stack
- Next.jsReactTypeScriptSQLiteDrizzlePuppeteerTailwind
In numbers
1
render path shared by the preview, the PDF download and the issued view, so they cannot differ
0
silent currency fallbacks: a missing ECB rate raises an error
0
automated tests
The problem
Invoicing for a Bulgarian company has fixed rules: gap-free sequential numbers, a VAT-article note chosen by client type, euro amounts at the ECB rate for the tax-event date, and corrections by credit note. I wanted a tool that enforces those rules instead of relying on me to remember them.
The approach
I wrote a 384-line platform spec first, then had agents build a single-tenant Next.js app on SQLite and Drizzle. The numbering and the VAT notes were checked in-session against Bulgarian VAT law and Ordinance N-18.
How it works
One render path
Euro conversion is a render-time transform in one template function, so the preview, the PDF download and the issued view run through the same code and look the same.
Exchange rates that fail loudly
The ECB rate is fetched for the tax-event date and persisted to a disk cache. The silent USD fallback was removed, so the renderer and the form raise an error when a rate is missing, and manual entry is the explicit override.
Corrections without edits
Issued documents are not edited. A mistake is corrected with a credit note and a reissue, and the numbers keep running in a gap-free sequence.
A backup before the counter moves
The database is backed up with a timestamp before any change. After an agent overrode precedent on an irreversible issue step, I recorded the rule that on an issue step precedent wins, and any conflict gets a question before the counter moves.
A sanitised copy for someone else
When I handed the tool to another person, agents audited each source file, applied 39 scripted patches and built a 106-file archive with no database, logo, spec, environment files or git history. A leak sweep covered all files plus the text and metadata of the explainer PDF, which a Puppeteer render produced in six pages with bundled fonts.
What I chose, and what lost
Chose
Failing loudly on a missing exchange rate
Over
A silent USD fallback
A fallback would put a wrong figure on a legal document without anyone noticing.
Chose
A credit note and a reissue
Over
Editing an issued invoice
The issued document stays as it was and the number sequence stays gap-free.
Outcome
It issues my invoices. It sits on a private network with no login inside the app. It has no automated tests, which is its weak point; its correctness rests on the single render path and on the rules above.