Case study · A commercial waste-audit consultancy
Offline-First Waste Audit Field Platform
A native, offline-first PWA that replaced a stalled no-code v1 — multi-floor tenant model, composition sliders constrained to a 99–101% sum, batch photo upload, async voice transcription, immutable report snapshots, and tokenized public PDF reports.
Headline outcome
Field assessors complete multi-tenant audits offline in basements and lift cores; admin sign-off issues an immutable report and a tokenized PDF in one tap.
The brief
A no-code v1 had been built but never deployed. It forced single-location-per-stream, photo-per-bin, no multi-floor support, and free-text composition entry — none of which matched how a real waste audit actually runs. The consultancy needed a native rebuild that fit the true shape of the work — multi-floor, multi-location, multi-stream — and survived cellular dead zones in basement loading docks and lift cores.
They asked us to build it as a custom app for their field-operations team, production-ready from day one, so it could go straight from kick-off into daily field use.
What we built — for the field assessor
A mobile-first, offline-tolerant flow shaped around how an assessor actually walks a building.
- Multi-level tenant hierarchy with on-the-fly location adds during a visit. Level labels deduplicate case-insensitively and trim-normalised, so subtle spelling variants of the same floor collapse to one row instead of fragmenting the data.
- Four priority streams visible by default with a "+ More" reveal for the rest of the catalogue. Assessors hit the common case in one tap and reach the long tail when they need it.
- Bin records per (location, stream) with size, count, emptying cycle, and fullness percentage.
- Volume-weighted Combined Fullness % rolled up per stream across every location in the assessment — the figure the report actually needs, computed from the data the assessor already entered.
- Composition sliders constrained to a 99–101% sum, with a live red / yellow / green indicator and an Auto-balance largest slider affordance. Submit is blocked outside the band; the constraint is enforced again at the database layer as a deferrable CHECK so multi-row inserts during offline drain settle correctly.
- Batch photo upload per stream (not per bin). Multi-select from the camera roll, reorder, queued via the offline sync layer, uploads never block the rest of the workflow.
- In-browser voice notes via the MediaRecorder API, transcribed asynchronously by Whisper on a Supabase Edge Function. A voice note can sign off with
transcript_status = 'pending'; the report renders "transcript pending…" and reconciles automatically once the transcript completes. - Standard-recommendation chips plus a single free-text custom recommendation per assessment.
- A "Ready for sign-off" state the assessor sets but cannot self-approve.
What we built — for the admin
A separate, role-gated surface for the people who own the data and the output.
- Full CRUD on portfolios, sites, tenants, and tenant levels, with
ON DELETE RESTRICTon the FK from captured locations so a referenced level cannot be orphaned. - Reference-data CRUD across streams, bin sizes, locations, materials (per-stream × business-type filtering), recommendations, and emptying cycles. Curated reference tables — never free-text picklists — so the captured data has no terminology drift and is clean enough for downstream BI export later.
- User invite, role change, and deactivation.
- Sign-off button that immutably snapshots the assessment and issues a tokenized public report URL in one action.
- Reopen flow that creates a new snapshot on re-sign and revokes the prior link — the previous tokenised URL returns
410 Gone, the old snapshot stays for audit, and the new snapshot gets a fresh URL. - Server-rendered web report plus on-demand PDF download.
How we built it — production stack from day one
- Next.js 14 (App Router) + TypeScript. Server components by default; role-gated route groups for the assessor and admin surfaces.
- Supabase for Postgres, Auth, Storage, and Edge Functions. RLS on every table. Role is read via a JWT
custom_access_token_hookwithpublic.is_admin()andpublic.is_field_assessor()helpers, not raw JWT inspection at every query. - Offline-first PWA via
@serwist/nextfor the service worker andidbfor the IndexedDB queue. Mutations queue on network failure, drain on the browseronlineevent, with idempotency via per-rowclient_idcolumns plus partial unique indexes, FK ordering preserved across queued items via a drain-scoped client-id → server-id translation map, and a cross-tab drain mutex vianavigator.locksso two open tabs cannot replay the same queue twice. - Whisper transcription on a Supabase Edge Function — async by design, never blocks sign-off, admin-retryable on failure.
- PDF rendering on a Vercel Node serverless function using
@sparticuz/chromium+puppeteer-core. Node runtime rather than Edge because Chromium cannot load on Edge. - Inventory pattern — three source-of-truth files (screens, actions, database access) maintained alongside the code, with a pre-commit validator that catches drift between an added route or table and the inventory entries.
- Tokenized public report URL with a random 32-byte URL-safe token, signed-URL photo delivery, and one active link per snapshot.
The five things that decided whether it would work in the field
- The composition-sum invariant enforced at the database layer as a deferrable CHECK constraint, so multi-row inserts during offline drain settle correctly without rejecting the whole batch.
- Curated reference tables across streams, bin sizes, locations, materials, recommendations, and emptying cycles. Free-text picklists would have made downstream BI export a recurring data-cleanup job; curated tables make it a one-shot mapping.
- The async-Whisper rule. The transcription pipeline is decoupled from sign-off entirely. The report renders the placeholder until the transcript completes and reconciles itself. The assessor and the admin never wait on a model.
- Tenant-level upsert dedupe with case-insensitive, trim-normalised matching and
ON DELETE RESTRICTon the captured-location FK. Orphaning a referenced floor label is structurally impossible. - Immutable
report_snapshots. RLS allowsINSERTandSELECTbut noUPDATE. Every reopen issues a new row, every old row stays for audit, and the trail is intact by construction rather than by discipline.
The result
A single field-tested platform replaced a no-code build that had stalled before deployment. Field assessors can now complete a full multi-tenant audit on a phone in a basement with no signal. Sign-off, immutable snapshot, tokenized report URL, and PDF download are one button each for the admin. Report layout is consistent across audits and ready to feed downstream reporting without a per-audit clean-up pass.
Other case studies
Customer Service Portal: Claims, Refunds, Coupons
Service console across three markets for claims, refunds, coupons and tech support — wraps WooCommerce, the claims DB and Make.com as sources of truth.
Field Operations Platform for Multi-Project Staffing & Coordination
A unified field operations platform that lets a small admin team run multiple parallel projects with hundreds of people deployed across different locations. One system for staffing, scheduling, in-app attendance, end-to-end travel and carpool coordination, AI-reviewed expenses and onboarding, AI-summarised field notes, live earnings, compliance, automated daily reporting, and direct Claude access for admins via the Model Context Protocol (MCP).
Role-Aware Claude MCP + Company Second Brain
A Claude.ai connector that lets every member of an operations team chat with live production data — each person scoped by role, with a company second brain on top.
Start a conversation
Ready to build something
that actually works?
No hard sell. We listen, understand your challenge, and tell you honestly whether we can help — and how.