Aurora Ops
Offline-first, AI-assisted field-ops platform for FMCG distribution

Overview
An internal, role-based web platform that digitizes a Nigerian FMCG/beverage distributor's field operations: outlet visits, resource/asset requests, multi-step approvals, compliance inspections, inventory, and e-signed contracts. It runs as an offline-first PWA for low-connectivity field work and layers a GPT-4o assistant on top for risk scoring and decision support.
My role
Solo full-stack build. Scope covered the Prisma data model (~23 models), the two-layer auth/RBAC system, the configurable approval engine, the offline-sync/PWA layer, the GPT-4o integration, and the full Next.js App Router UI (~37 dashboard pages, shadcn-style component library).
The problem
FMCG field operations for a nationwide beverage distributor are typically run on paper and spreadsheets: field agents visit outlets in areas with unreliable connectivity, high-value assets (coolers, dispensers, signage) are requested and approved through informal multi-level chains, and compliance inspections and warehouse inventory are tracked ad hoc. This makes approvals slow, asset allocation hard to justify, and the audit trail thin (a problem across an 8-level org hierarchy from field agents to executives).
The solution
A single Next.js 16 PWA covering the whole lifecycle (request → multi-step approval → contract/e-signature → fulfilment) that keeps working offline and syncs a checksummed mutation queue when connectivity returns. Authorisation is modelled as two orthogonal layers (a flat role/permission matrix plus geographic row-level scoping), enforced server-side on every route. Approval workflows are configurable data (no-code chains with value/type routing and auto-approve thresholds) rather than hardcoded logic, and GPT-4o is wired in for contextual chat, request risk scoring, inspection flags, and executive summaries, always with hardcoded fallbacks.
Key features
- 8-level role-based access control combined with geographic row-level data scoping (zone/region/territory/outlet), enforced on both client and server.
- Configurable no-code approval engine: multi-step chains matched by resource type and quantity band, with auto-approve thresholds and modification/resubmit branches.
- Offline-first PWA: service worker, Dexie/IndexedDB queue, SHA-256-checksummed mutations, pre-downloaded outlet/catalogue data, and auto-sync on reconnect.
- Compliance inspections (checklist scoring, reassessment workflow) and inventory management (stock-take, dispatch/restock/write-off, before/after audit history).
- Contract generation with hand-drawn or typed e-signature (react-signature-canvas), 30-day validity, and sign/void state transitions.
- GPT-4o assistant with live Prisma aggregates injected as context, plus bulk .xlsx import, Cloudinary uploads, Resend email, and Pusher real-time notifications.
Architecture & engineering
Next.js 16 App Router (with the new proxy.ts middleware) on React 19 + TypeScript. Data is PostgreSQL on Supabase accessed via Prisma 7 with the pg driver adapter, using a pooled connection at runtime and a direct URL for migrations. Authz is two orthogonal layers: a static permission matrix (usePermissions client-side; requirePermission → 401/403 server-side) plus buildGeoFilter row scoping. Approval chains are DB-modelled and executed as a sequential step-instance state machine. AI follows a "RAG-lite" pattern: routes pull live domain aggregates, inject them as prompt context, and extract structured JSON with per-feature temperature tuning. UI is a Base UI + Tailwind v4 shadcn-style component library, a single Zustand store, Recharts, and TanStack Table/Virtual.
The hardest problem
The core challenge was making the app trustworthy offline. The solution queues mutations client-side in IndexedDB with a SHA-256 checksum and a userId+deviceId+checksum idempotency key, flushes them to a sync endpoint via the Background Sync API and on-reconnect, and purges local copies after sync.
Key learnings
Modelling authorisation as two independent axes (what you can do vs. which rows you can see) keeps access rules clean as roles multiply. Treating approval workflows as configurable data instead of code makes the business logic far more adaptable. And keeping AI features useful required pairing every model call with a deterministic fallback so the app never hard-depends on the LLM.
Curious how this works?
This one's a private build; request a walkthrough and I'll show you around.