← All work

Case study · Food safety

HACCP Compliance

For a small food producer, HACCP is not optional, but managing it can quickly become an administrative system larger than the business itself. This is a digital HACCP and traceability application built around how an artisan smokehouse actually works, so that the evidence of safe production is a by-product of producing the food rather than paperwork completed around it.

Role
Product owner & sole engineer
Status
In daily production use
Stack
React 19 · TypeScript · Supabase
Scale
~39K LOC · 21 migrations · 77 test files

The problem

Paperwork is not the same as proof

The records are real work

A small producer has to show that hazards were identified, that controls are in place, that critical checks were completed, that corrective actions were recorded, and that any product can be traced through the process. Traditionally that lives across paper forms, spreadsheets, temperature logs, cleaning records, production notes and separate traceability documents.

Having a system is not the same as showing it

The harder problem is evidence. A folder of forms proves that forms exist. It does not readily answer what was made, from which raw materials, from which supplier, whether temperatures held, what happened when something fell outside its limits, and where the product went. Reconstructing that from invoices and notebooks is exactly the work nobody has time for on the day it is asked for.

Batch lookup: 48 production records with batch codes, products, supplier lots, dates and status
Every production record in one searchable list, by batch code, product or supplier lot. The indented rows are fragments: part of a batch sliced and packed later, carrying its own code and date.
Product library: 13 products configured with HACCP process templates, each showing stages, duration and shelf life
Products are process templates, not catalogue entries. Each one carries its stages, expected duration, shelf life and allergens, so a new run starts already knowing what has to be controlled.
CCP deviation report: total deviations, resolved and pending, with variance against expected stage duration
The deviation report an Environmental Health officer would ask for. These are timing variances against each product's process template, caught automatically, and each one stays listed until a corrective action is recorded against it.
A laboratory test report with aerobic colony count, Enterobacteriaceae and E. coli results, each marked satisfactory
Laboratory and environmental swab results live alongside the production data and can be linked to the batch they belong to, so the microbiology and the process record are one history rather than two filing systems.

The approach

Production as a sequence of controlled events

The important decision was not to build a generic compliance form. Controls appear at the point in the process where they matter, which is the difference between software that records the work and software that gets in the way of it.

The batch is the record

  • Production is modelled as a sequence of controlled events rather than a set of documents. A production run is the central row, and ingredients, supplier lots, stage timings, temperatures, lab results, attachments and corrective actions all hang off it.
  • The application prompts for what is needed at the stage where it is needed, rather than relying on someone remembering which form is outstanding.
  • The audit trail is therefore a by-product of making the food, not a second job done around it.

Controls shaped like the actual process

  • Products are defined as process templates: named stages, expected durations, temperature ranges and shelf life. The smokehouse currently runs 13 of them, from cold-smoked trout at seven stages to a five-stage gravlax.
  • Expected durations are enforced. A stage that runs long or finishes early is flagged automatically as a deviation, with the variance calculated, and it stays on the report until a corrective action is recorded against it.
  • A recipe calculator defines quantities once and scales ingredients to batch weight, including compound ingredients built from other ingredients.

Traceability designed in, not bolted on

  • Supplier lots attach to production runs, and finished products link back through the process, so the forward and backward trace both already exist as data.
  • Runs can be fragmented at the storage stage: a batch that is partly sliced and packed becomes a parent run with child fragments, each carrying its own code and date, because that is what actually happens on the bench.
  • A public batch lookup lets a customer or an inspector resolve a code without an account. It is a separate database function that deliberately returns sanitised data only: ingredients and allergens yes, internal times, quantities, critical-control data and notes no.

How it is built

Small business, serious foundations

Multi-tenant from the schema up

  • Postgres on Supabase with row-level security on every table, plus organisation membership and role checks, so isolation is enforced by the database rather than remembered by the UI.
  • Roles for admins, operators and viewers, with invitations handled by Edge Functions, and per-organisation theming so the product can carry another producer's branding.
  • An append-only audit log: every action recorded with a timestamp and the user who took it.

Built to be used on a wet bench

  • React 19 and Vite with Tailwind, fully responsive, because the person logging a temperature has a phone in one hand and is not sitting at a desk.
  • Realtime subscriptions so a run started on one device shows up on another, with countdown timers on stages that are waiting.
  • Sensor readings can be imported and charted, and certificates, lab reports and photos attach to a batch with scoping that keeps them findable later.

Checked like something people depend on

  • 77 test files across Vitest with React Testing Library and Playwright end-to-end specs, run against a local Supabase stack rather than mocks.
  • Accessibility assertions with jest-axe, error boundaries around the risky surfaces, and generated database types so a schema change breaks the build rather than a shift.
  • A single CI command covering lint, typecheck, coverage and build.

Outcomes

What it replaced

A collection of disconnected food-safety requirements became one operational workflow. The same records that exist to satisfy a regulator are now structured data the business can actually read: batch history, process consistency, recurring exceptions and where a procedure could be improved.

  • Digital HACCP and production records
  • Batch-level traceability, forward and backward
  • Supplier and ingredient records
  • Process and temperature monitoring
  • Critical control point recording
  • Corrective-action history
  • Lab and environmental test results
  • Searchable production history
  • Stronger audit and inspection evidence
  • Structured operational data for later analysis

Role & context

Vii Dohtem is Method7's own venture, a small artisan smokehouse producing cured and smoked fish, and this application is our own software. We designed and built it single-handed, and it runs the real production process rather than a demonstration of one. That is the reason it works the way it does: the stage model, the fragmentation at slice and pack, and the timing deviations all come from watching the operation get in the way of the paperwork, and then the paperwork get in the way of the operation.

It is now being offered to other food producers, and is in active development. Full HACCP documentation export and built-in hazard analysis are the next things on the list. See the wider venture in the Vii Dohtem platform case study.

Got an operation that runs on spreadsheets?