CASE FILE
FAKTS
Invoicing that satisfies a bureaucracy
THE ASK
A spreadsheet cannot be an e-invoice.
Latvia is moving every business invoice to a structured, machine-readable format. Public sector already, everyone else by 2028. Most Latvian freelancers and small companies still invoice from a template and a PDF export, which will stop being a legal document. Build the thing they move to, and make it pleasant enough that they move early.
deadlines are the easiest brief to scope against.
THE CONSTRAINTS
2025 · 01 · 01
Structured e-invoicing mandatory for invoices to the state.
2026 · 03 · 30
Business to business opens voluntarily. The window we are building in.
2028 · 01 · 01
Mandatory for everyone, and the data must reach the tax authority within five working days of issue.
- Format
- Peppol BIS 3.0 over UBL 2.1, to EN 16931
- Addressing
9939:LV40003XXXXXX, the Latvian VAT scheme- Numbering
- Unique and sequential per series. EU VAT Directive art. 226(2), Cabinet Reg. 877 §28
- VAT
- Every standard Latvian tier, plus reverse charge and exempt lines
none of this is negotiable. that is what makes it interesting.
THE NUMBER
A draft holds no number. It gets one at issue, or not at all.
An invoice series may not have a hole in it. Not a convention, a legal requirement, and the first thing an auditor counts. So two people issuing in the same second must not collide, and a request that fails halfway must not burn a number on the way out.
Allocation takes a row lock, SELECT … FOR UPDATE, on the sequence for that tenant, that series, that year. The number is handed out at issue and the document is frozen into an immutable snapshot in the same move.
the counter on this deck runs the same way. it has never skipped either.
THE RECORD
Nobody should retype a company's legal address. Fakts keeps its own nightly mirror of the Latvian Enterprise Register and the state address register, pulled from the open data portal. Type three letters of a client's name and the official record fills the form.
- Legal name
- SIA KAISMA
- Reg. no.
- 40003XXXXXX
- VAT
- LV40003XXXXXX
- Address
- Brīvības iela 000, Rīga, LV-1010
FILLED FROM THE REGISTER · SYNCED NIGHTLY
typed data is wrong data, eventually.
THE INTAKE
Invoices you receive arrive as email attachments, which is where bookkeeping goes to die. Connect a mailbox and Fakts polls it, queues the attachments, and extracts each one into a draft with supplier, number, dates, lines and VAT already filled in. A person confirms it. The machine never books anything on its own.
IN
MAILBOX
Polled on a schedule, read only.
QUEUE
ATTACHMENT
Stored, deduped, waiting.
MODEL
EXTRACT
Fields pulled from the document.
STOP
YOU CONFIRM
Nothing is booked until a person says so.
the useful part of an agent is knowing where to make it stop.
THE BUILD
CLOUDFLARE
- SvelteKit on Workers
- Static assets, global
- R2 for files, EU routed
- Presigned uploads
GO API
- net/http, no framework
- sqlc over raw SQL
- Caddy terminates TLS
- Postgres 16 beside it
WORKERS
- Document ingestion
- Mailbox polling
- Recurring invoices
- Register sync, ECB rates
One rule holds the money side together: the server recalculates every financial field before it writes, and returns the record it stored. The interface never decides what a total is, it only shows what the database agreed to.
boring infrastructure, on purpose. it has to still be here in 2028.
THE SPEC
| Frontend | SvelteKit, TypeScript, Svelte 5 runes, Cloudflare Workers |
|---|---|
| Backend | Go, standard library net/http, sqlc |
| Database | PostgreSQL 16, pgxpool, row-locked numbering sequences |
| Documents | UBL 2.1 / Peppol BIS 3.0 XML, PDF, EPC QR payment codes |
| Files | Cloudflare R2, presigned uploads, EU data routing |
| Auth | Google OAuth, JWT in an HttpOnly SameSite cookie |
| Extraction | Anthropic API, feature gated, human confirms every result |
| Open data | Enterprise register and address register mirrored nightly |
| Languages | Latvian and English, with a separate per-document language |
| Hosting | Cloudflare edge, one Oracle VPS, nightly database dumps |
every optional piece degrades quietly instead of breaking the app.
WHERE IT STANDS
LIVE
fakts.lv, LV and EN
8
permissioned modules
2028
compliant ahead of the mandate
1
server, deliberately
Outgoing invoices, quotes, incoming documents, royalties, a client book, a calendar and VAT reporting, across multi-company tenants with module-level permissions. The public site prerenders to static HTML in both languages.
that is the file. the agent takes it from here.