From paper request form to signed PDF report: a histology LIMS with barcode chain of custody and an audit trail on every action.
Project Summary
- Client: Aroha Cancer Centre
- Industry: healthcare
- My role: Lead Engineer & Architect
- Core tasks: System architecture, Lab workflow design, Web app, Cloud Functions, Label printing
- Appointed date: Jul 2026
- Completion: Ongoing
A histology lab handles hundreds of small, irreplaceable objects every week: specimens, cassettes, wax blocks and glass slides. Each one must trace back to the right patient, and every report must be signed, versioned and defensible. At Aroha Cancer Centre in Meru that was done on paper. I'm building the system that replaces it.
The problem
- Paper chain of custody. Request forms, handwritten labels and logbooks make it hard to prove where a specimen is or who handled it.
- Reports without history. A correction to a signed report must never overwrite what was originally issued.
- Accreditation pressure. ISO 15189 expects traceability, audit trails and controlled signatures.
What I built
- Accessioning. A paper request form becomes a case with a human-readable accession number such as H26-00001.
- Barcode identity graph. Specimen, cassette, block and slide each get an immutable barcode that doubles as the database ID, so scanning whatever is in your hand opens exactly that object.
- Scan-driven lab tracking. Every stage change is recorded with the barcode, the time and the person.
- Label printing. A print agent on the lab network takes jobs from a Firestore queue and prints ZPL labels on Zebra printers.
- Pathologist workbench. Case queue, report templates and second reviews, ending in a signed PDF report.
- Billing, retention and a client portal. Referring clinics follow their cases and download reports.
Under the hood
Clients never write tracked data directly. Every change goes through a Cloud Function built on a single mutate() primitive that writes the record and its audit entry in one transaction. Reports are append-only: each signature creates an immutable version, corrections become amendments or addenda that record what they supersede, and security rules deny any client write to past versions. The front end is a SvelteKit single-page app with shadcn-svelte and Tailwind, on Firebase Auth, Firestore, Storage and Hosting.
Where it stands
Accessioning, tracking and search, and the pathologist workbench with reporting are complete. The remaining go-live gates are validating labels on the lab's Zebra printers and the ISO 15189 signature review.
Tech stack
- SvelteKit
- Svelte 5
- TypeScript
- shadcn-svelte
- Tailwind CSS 4
- TanStack Table
- Cloud Functions v2 (Node 22)
- TypeScript
- Cloud Firestore
- Firebase Auth
- Cloud Storage
- Firebase Hosting
- bwip-js barcodes
- pdf-lib
- Zebra ZPL
What I did
- Designed the lab workflow, data model and barcode identity scheme
- Built the SvelteKit app and the audited Cloud Functions API
- Built report signing, versioning, amendments and PDF generation
- Built the Zebra label print agent and its Firestore job queue
Key decisions
- Every write goes through one audited server-side mutate() primitive
- Append-only, versioned reports; corrections never overwrite a signed version
- The barcode payload is the document ID, so a scan is a direct lookup
- A print agent on the lab LAN, fed by a cloud queue, instead of browser printing
Challenges
- Modelling a cassette and its block as one physical object at two stages
- Guaranteeing an audit record for every change, atomically
- Printing from a cloud app to label printers on a lab LAN
- Designing toward ISO 15189 accreditation from day one
Have a similar problem to solve? Let's talk.
Start a conversation