- Role
- Founder · product and build
- Company
- Personal
- Period
- Personal project
- Stack
- Next.js, TypeScript, Supabase, Anthropic Claude SDK
Context
The problem
At a 10–50 person Vietnamese company, one person often runs HR, operations and payroll at once. Vietnam updates minimum wage, social insurance, overtime and tax rules by decree, and most small companies cannot afford a compliance specialist to keep up.
The tempting fix is a chatbot that "knows the law". The trouble is that a can sound certain while being wrong, and in compliance a confident wrong answer is worse than no answer.
Approach
The decision: the AI never makes the call
I split the work in two. The language model reads the document and pulls out facts: wage, probation length, overtime, clauses. A deterministic rule engine, with every limit stored next to the article it comes from, decides pass or fail. Then the model explains the result in plain Vietnamese.
The decision
Ask an AI for the answer, or keep the AI away from the verdict?
The model only reads the document and pulls out facts. A rule engine with every limit stored next to its article decides pass or fail. Then the model explains the result.
Cost I accepted: Coverage grows rule by rule: 27 seeded rules across 6 document types today. The 100+ on the landing page is the roadmap, not the count.
Source: Ledgr repository: src/lib/compliance (extractor.ts, engine.ts, narrator.ts); seed migrations 20260616000002 and 20260618000001.
Who decides what
- 01UploadPDF, Word or image
- 02AI extracts factsWages, dates, clauses
- 03Rule engine decidesEach limit cited to its article
- 04AI explains the fixIn Vietnamese, with the citation
If a wage sits exactly on the legal floor, the engine doesn't pass it. It asks a human.
Two details carry the trust. A value exactly at a limit is flagged, not passed. And when the engine cannot pin a rule (say, the contract never states its region), the finding is marked as not source-backed instead of guessed.
Cross-check
Where the real errors hide
A contract, a payroll sheet and a tax return can each pass alone and still contradict each other. So Ledgr also reads them together: the contract wage times twelve should match the income on the year-end tax return.
Outcome
What shipped
I demoed Ledgr at Build Stuffs #33 (20 June 2026), a builders' showcase in Ho Chi Minh City, and talked it through with around 20 people there. I kept showing it at the next sessions (#34 on 4 July, #36 on 1 August).
Results
- rules seeded across 6 document types (100+ is the roadmap)Live, seeded rules
- 27
- people I talked it through with at Build Stuffs #33My account
- ~20
Source: Ledgr repository: seed migrations 20260616000002 and 20260618000001 (rules added at runtime are not counted); my own account of Build Stuffs #33, 20 June 2026.





