Case study · 02 / 08
Fleet Flow
An IoT + ML fleet monitoring platform for a high-volume FMCG site — cameras at each station detect trucks and log every visit, and the platform turns those visits into live presence, turnaround durations and lost-time analysis so the site can optimise truck loading time.
- Scope, delivery and the technical decisions
- PM + Architect
- Which trucks are at which station, right now
- Live presence
- Where truck turnaround time actually goes
- Lost time
- Configurable reports, previewed and exported
- Excel + PDF

Context
Every minute a truck waits at a loading site is dispatch capacity lost, but without per-station data nobody can see where that time goes — which stations are busy or idle, how long each vehicle actually takes, and how much of it is lost time. Fleet Flow puts cameras at each station to detect trucks and record their visits, so turnaround becomes something the site can measure, report on and optimise instead of estimate.
I led Fleet Flow as project manager and software architect: I owned scope and delivery, and made the technical decisions — the system architecture and stack, how camera data reaches the platform, the security model, and the quality gates the code has to pass.
01
Detection decoupled from the platform
The camera side and the platform meet at the database, not in each other's code. Each station camera writes its detections into its own visit table — cam_1 through cam_10 — and the API derives live presence, visit history and durations from those rows. The detection model can be retrained or swapped without touching the API or the dashboards, and the platform runs and can be tested without a single live camera.
02
From raw visits to lost time
Visits only matter once they answer operational questions, so the platform rolls them up three ways: station views (availability, activity, which vehicles are on site right now), vehicle views (performance and duration insights per truck), and lost-time analysis that shows where turnaround time goes. Every registered vehicle gets a QR code, configurable reports preview in the browser and export to Excel or PDF, and Android-box wallboards put live station data on a screen at each station — served by the same Next.js app, so there is no second product to maintain.
03
Security and operability are requirements
Non-functional requirements are part of the design, not afterthoughts: JWT access tokens with refresh-token rotation, role-based access with granular permissions, an audit log and structured request logging, Helmet, a CORS allowlist and throttling, and liveness and readiness probes for monitoring. The API contract is published as Swagger/OpenAPI and checked into the repo, one validate script gates lint, formatting, type checks and the build, and a production checklist covers secrets, Swagger exposure and HTTPS.
04
A modular, typed stack
NestJS modules map one-to-one to the domain — auth, users, vehicles, stations, reports, health — over a Prisma schema with versioned migrations, and one setup command creates the database, migrates it and seeds the first admin and stations. The frontend is organised by feature, each with its own API client, hooks and types, with Redux Toolkit for state and React Hook Form + Zod for validated forms. Times default to the site's time zone, so durations and reports read in local time.
Stack & architecture
- Station cameras with IoT + ML truck detection, writing visits into per-camera tables (cam_1 … cam_10)
- NestJS 11 REST API under /api/v1 — auth, users, vehicles, stations, reports and health modules
- Prisma 6 on MySQL 8 or MariaDB, with versioned migrations and a one-command setup and seed
- Next.js 16 App Router + React 19 dashboard; Redux Toolkit, Tailwind CSS 4, Radix / shadcn UI, Recharts
- Android-box station wallboards served by the same Next.js app
- JWT + Passport + bcrypt auth with refresh-token rotation; role-based access with granular permissions; audit log
- Helmet, CORS allowlisting and throttling; liveness and readiness endpoints for monitoring
- ExcelJS and PDFKit report exports; optional email delivery via Nodemailer
- Swagger UI plus a checked-in OpenAPI document as the API contract
- Next.js 16
- React 19
- NestJS 11
- Prisma
- MySQL
- Redux Toolkit
- Tailwind CSS
- Recharts
- OpenAPI