Case Study - One Core, Three Shells: Invoicing Engineered Like Real Software
An offline-first, SARS-compliant invoicing and bookkeeping product for South African small businesses: one Zig core linked into desktop, web and native shells, with integer-cents money and 334 automated tests.
- Client
- Tekolo
- Year
- Service
- Systems Engineering, Cross-Platform Architecture

- Automated tests across Zig and TypeScript
- 334
- Platform shells on one Zig core: shipped, in progress, planned
- 3
- Third-party dependencies in the PDF engine
- 0
- Offline: SARS-compliant with no cloud dependency
- 100%
Impact
Tekolo is my own product: invoicing and bookkeeping for South African small businesses that works fully offline, satisfies SARS requirements out of the box, and charges no monthly fee. It sits in this portfolio for a specific reason: it is the clearest demonstration that “engineered like real software” is a working method rather than a slogan. There is no client behind it and no data story inside it: just a production codebase, built solo, held to the same standards I bring to client systems.
That standard is concrete. Every monetary value in the system is an integer number of cents on every layer (database columns, Zig structs, JSON wire formats, TypeScript types), so floating-point money errors are structurally impossible. Rounding happens in exactly one place. Invoice totals are computed by the server and only by the server. Compliance rules are enforced where they cannot be bypassed. And 334 automated tests, including contract tests that run the real binary instead of mocks, hold the whole thing together.
Core: money that can’t be wrong
The heart of Tekolo is a Zig core library that owns all business logic, the SQLite database (WAL mode, versioned migrations), and PDF generation. Its money-handling rules are strict: amounts live as integer cents everywhere, and all rounding flows through a single banker’s-rounding function (one boundary, one behaviour, tested directly). When the frontend submits an invoice, the core recomputes every subtotal, VAT line and total itself, ignoring whatever the client sent; a compromised or buggy UI cannot produce a wrong invoice.
South African compliance is enforced at the same depth. VAT is fixed at 15% and validated in both the calculator and the compliance checker, which hard-errors rather than warns. VAT numbers, CIPC registration numbers, bank branch codes and sequential invoice numbering (a SARS requirement) are all validated at the FFI boundary before anything touches the database.

The PDF invoices come from a pure-Zig PDF writer with zero third-party dependencies: no headless browser, no C library, just bytes written to the PDF specification.

- Zig
- SQLite (WAL)
- TypeScript
Shells: one core, many surfaces
The same Zig core reaches users through multiple shells without forking its logic. On the desktop it compiles to a C ABI static library linked directly into a Tauri 2 (Rust) binary: every call is an in-process function call through extern "C" exports, with no subprocess and no serialisation overhead on the hot path. The Svelte 5 frontend talks to Rust over Tauri IPC; Rust calls straight into Zig.
The same core already compiles to WebAssembly (wasm32-freestanding), the working foundation for a planned browser PWA. A native Linux shell, pure Zig with GTK4 and libadwaita with no webview at all, is in progress. Adding a shell is a deliberate, bounded exercise: the business logic, the database layer and the PDF writer never change.

- Rust / Tauri 2
- Svelte 5
- WASM
- GTK4 (in progress)
Proof: the test story
Tekolo carries 334 automated tests: 106 in Zig covering the core (handlers integration, PDF smoke tests, company isolation) and 228 in Vitest covering the frontend. Five of those are contract tests with no mocks anywhere: they invoke the real Zig CLI, capture its actual JSON output, and assert the TypeScript types against it, so the two sides of the FFI boundary cannot silently drift apart.
CI runs the full gauntlet on every push: Zig tests, Vitest, ESLint, Prettier, a complete Tauri release build, and a security audit. The product has no users yet (it hasn’t launched), and that is the point of showing it: the discipline is the deliverable. This is what my default engineering standard looks like when nobody is watching.
About Tekolo
Tekolo is invoicing and bookkeeping software for South African small businesses: sole traders and small teams who need SARS-compliant invoices, expense capture and VAT tracking without a monthly SaaS fee or a mandatory cloud account. The full local workflow is free and works offline; the roadmap adds a browser PWA and a native Linux app on the same core, with optional paid hosted services only for the things that genuinely cost infrastructure money.
Challenge
The hard part is keeping three languages honest across one boundary, alone. The C ABI surface had to stay frozen through a major Zig upgrade that changed the language’s entire I/O model: solved by constructing the threaded I/O runtime per-call at the FFI edge so external signatures never moved. The Rust shell treats the Zig library as hostile: database paths are canonicalised and prefix-checked against the app data directory, enforced structurally so a Tauri command that skips validation fails to compile. And every shell added must prove it changes nothing beneath it. The moment business logic forks per platform, the one-core thesis is dead.