Skip to content
Back to projects

Private client work · Case study

Tabula

Result

Shipped to a client as a Windows installer, built solo in four months

Tabula workspace: rules sidebar, data table with before-and-after value chips, and the Inspector panel

A desktop app for building repeatable CSV workflows without writing code: typed rule blocks on a visual canvas, a row-by-row explanation of every change, and a replayable audit of every export.

ElectronReactTypeScriptSQLiteZustandMantinednd-kitVitestPlaywright

Private client work. Tabula shipped to a client as a Windows installer and is in beta. The source is private, and every screenshot here uses the app's generic sample data (a fictional hardware store).


Overview

Plenty of businesses run on spreadsheets that someone updates by hand: re-pricing inventory, dropping rows that shouldn't ship, flagging anything that looks wrong. Tabula turns that routine into a workflow you can rerun.

You open a primary CSV and link reference files joined on a key column. Then you build three kinds of rules: Exclude rules drop rows, Modify rules rewrite values, and Alerts flag rows without changing them. Every cell shows how its value changed, and the Inspector traces exactly which rules touched a row and why. When you finalize, Tabula writes the output CSV and saves an audit you can reopen later, read-only.

I built it solo between April and July 2026: 236 commits across 23 planned phases.

  1. Primary + linked CSVs
  2. Exclude · Modify · Alert rules
  3. Inspector trace
  4. Export + audit
Data flows through typed rules; every change is traced per row and every export is saved as a replayable audit.
Tabula workspace: Exclude, Modify and Alert rules on the left, a data table with status column and before-and-after value chips, and the Inspector with a pipeline trace

The workspace: rules, data, and the Inspector

The workspace: rules, data, and the Inspector
Rule editor showing a WHEN condition built from nested And and Or blocks comparing linked and primary columns

Rules are trees of typed blocks

Rules are trees of typed blocks
Rule editor showing a SET block with a Max expression, and a dimmed unconnected block below it that does not run

Unconnected blocks stay on the canvas, dimmed and inactive

Unconnected blocks stay on the canvas, dimmed and inactive
Inspector pipeline trace with three rule cards showing a price moving from 7.99 to 6 to 7.267 to 7.25

Per-row pipeline trace

Per-row pipeline trace
Finalize and export dialog with a column checklist, a changed-rows-only toggle and an audit label field

Finalizing an export

Finalizing an export
A reopened audit in a read-only tab labelled May price refresh, with editing controls hidden

Past exports reopen as read-only audits

Past exports reopen as read-only audits

Technical Highlights

Unit tests
~810
Playwright scenarios
~60
Commits
236
Logged decisions
60+
  • A typed rule language with a visual editor. Rules are trees of typed blocks: WHEN and SET, And/Or/Not, comparisons, arithmetic, rounding, and aggregators. Slots are colored by type, so blocks only fit where they make sense. Blocks that aren't connected stay on the canvas, dimmed and inactive, like code outside main(). Older rule formats migrate forward automatically.
  • Evaluation that tolerates messy data. A missing link, a type mismatch, or a divide by zero is a typed failure, not a crash. Boolean logic is three-valued, a failure that reaches a rule's condition or output becomes a typed automatic exclusion, and an engine error rolls that row back while the run continues. Every rule leaves a per-row trace for the Inspector.
  • Replayable audits. Finalizing stores a compressed snapshot of the inputs and the workflow, plus the engine version and a SHA-256 hash of the export. Past results are rebuilt by re-running the engine, and tests verify that replays reproduce the original output exactly.
  • One file per document. Each .tabula document is a self-contained SQLite database with the CSVs embedded as compressed blobs, a versioned schema that migrates in place, and crash recovery for unsaved work.
  • Configurable editions without forking. The same engine can ship a domain-specific profile of default settings, column-name aliases, and preset rules, without changing the core or the branding.
  • Tested end to end. About 810 unit tests, plus about 60 Playwright scenarios that drive the real Electron app through test-only hooks. The same harness regenerates the in-app Help screenshots. electron-builder produces a Windows installer and macOS builds for Intel and Apple Silicon.

Process

Tabula started as a single-purpose tool and was redesigned partway through into a general rule engine. That kind of pivot only works with a clear record of what was decided and why. I kept a scope document, a data model, and a numbered decision log with more than 60 entries, which code comments cite directly, and designed major changes in Figma and planning documents before building them. I used Claude Code throughout, with those documents as the shared context.