Live demo: fleetcheck-1.onrender.com — backend API at fleetcheck-j4y2.onrender.com
Hosted on Render's free tier, so the first request after a period of inactivity may take 30-60 seconds to wake up.
A digital Driver Vehicle Inspection Report (DVIR) system built to replace a paper-and-carbon-copy process at a Cintas route-service operation.
Drivers currently fill out a paper DVIR booklet at the start and end of every shift — a white original that stays in the book, a pink copy turned in daily. In practice this means illegible handwriting, delays getting reported defects to a mechanic, sheets that get lost, and drivers losing time on a process that should take under a minute. FleetCheck moves that workflow online: fast structured entry for drivers, a real repair workflow for mechanics, and a live dispatch-status view for fleet managers — with paper explicitly treated as a fallback, not the default.
- Role-based workflow — Driver, Mechanic, Fleet Manager, and Admin roles, each with a distinct view and distinct permissions enforced server-side (Spring Security), not just hidden in the UI
- Status workflow engine — inspection reports move through a validated state machine (see below), with every transition checked server-side
- Live dispatch-status derivation — a vehicle's dispatchability is computed on demand from its open safety-critical repairs, never cached or manually toggled
- Interactive damage diagram — click-to-place damage markers on front/side/rear truck silhouettes, using the same damage-type legend (Chip/Hole/Dent/Broken/Missing/Scratch/Rust/Other) as the physical paper form
- Mechanic repair queue — an actionable, three-stage queue (needs repair order → ready to complete → awaiting driver review), not just a filtered list
- Fleet & vehicle history views — a fleet-wide dispatch-status table and a full per-vehicle inspection/repair/damage timeline
- Account administration — admin-only user management with deactivation (not hard-delete), write-only password handling
- Test coverage — 37 backend tests (JUnit 5 + Mockito unit tests on the workflow engine; MockMvc + Spring Security Test integration tests exercising the full DVIR lifecycle through real HTTP and real authorization rules) and 22 frontend tests (Vitest + React Testing Library)
- CI/CD — GitHub Actions runs the full test suite on every push and pull request; deployed on Render with a separate production Spring profile, PostgreSQL, and CORS-aware cross-origin setup
stateDiagram-v2
[*] --> SATISFACTORY: No repair needed
[*] --> REPAIR_REQUESTED: Repair needed
REPAIR_REQUESTED --> REPAIR_COMPLETED: Mechanic completes repair
REPAIR_COMPLETED --> REVIEWED_CLOSED: Driver reviews and closes
SATISFACTORY --> [*]
REVIEWED_CLOSED --> [*]
A vehicle stays blocked from dispatch for any open SAFETY/BOTH repair until it reaches REVIEWED_CLOSED — repaired-but-unreviewed is still blocked, matching the physical form's two-signature requirement (driver reports → mechanic repairs → driver reviews).
- ARCHITECTURE.md — layered design, domain model, and the reasoning behind the key decisions (the status state machine, derived dispatch status, RBAC layout, DTO boundary)
- API_REFERENCE.md — full endpoint reference: routes, required roles, request/response shapes, error format
| Layer | Stack |
|---|---|
| Backend | Java 21, Spring Boot 3.5, Spring Data JPA, Spring Security, H2 (dev) / PostgreSQL (prod) |
| Frontend | React 18, TypeScript, Vite, Tailwind CSS v4 |
| Testing | JUnit 5, Mockito, MockMvc, Spring Security Test, Vitest, React Testing Library |
| CI/CD | GitHub Actions, Render (web service + static site + managed Postgres) |
fleetcheck/
├── src/
│ ├── main/java/com/fleetcheck/
│ │ ├── domain/ # JPA entities and enums
│ │ ├── dto/ # Flat request/response DTOs
│ │ ├── repository/ # Spring Data repositories
│ │ ├── service/ # Business logic, workflow rules
│ │ ├── controller/ # REST endpoints
│ │ ├── security/ # Spring Security config, auth
│ │ ├── config/ # CORS and OpenAPI configuration
│ │ ├── exception/ # Custom exceptions, global handler
│ │ └── seed/ # Dev seed data / production bootstrap admin
│ └── test/ # Unit + integration tests
└── frontend/ # React + TypeScript SPA
└── src/
├── api/ # Typed API client
├── auth/ # Auth context, protected routes
├── components/ # Shared UI (app shell, damage editor)
└── pages/ # Route-level views
Prerequisites: JDK 21+, Maven, Node 18+
Backend
mvn spring-boot:runRuns on http://localhost:8080 using an in-memory H2 database. Seed data and dev accounts load automatically on first boot — this seeding only happens locally; production uses a single bootstrap admin account created from environment variables instead (see Deployment, below).
Frontend
cd frontend
npm install
npm run devRuns on http://localhost:5173, proxying /api requests to the backend.
Dev accounts (local only, password: password123 for all)
| Username | Role |
|---|---|
driver1, driver2 |
Driver |
mechanic1 |
Mechanic |
manager1 |
Fleet Manager |
admin1 |
Admin |
API docs: interactive Swagger UI at http://localhost:8080/swagger-ui.html once the backend is running.
mvn testcd frontend
npm testDeployed on Render: a Dockerized Spring Boot web service, a React static site, and a managed PostgreSQL database, talking cross-origin over CORS.
Backend builds from the repo's Dockerfile (Render has no native Java runtime) and reads its configuration entirely from environment variables via the prod Spring profile:
| Variable | Purpose |
|---|---|
SPRING_PROFILES_ACTIVE=prod |
Activates the production profile (PostgreSQL, no dev seeding) |
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD |
Managed PostgreSQL connection |
ADMIN_BOOTSTRAP_USERNAME, ADMIN_BOOTSTRAP_PASSWORD |
Creates the single initial admin account on first boot if the accounts table is empty; the app refuses to start without them in prod |
CORS_ALLOWED_ORIGINS |
Comma-separated list of origins allowed to call the API (e.g. the frontend's Render URL) |
Once the bootstrap admin exists, it's used to sign in and create real driver/mechanic/manager accounts through the Accounts page — no other accounts are seeded in production.
Frontend is a static site build (npm run build) with one build-time variable:
| Variable | Purpose |
|---|---|
VITE_API_BASE_URL |
Base URL of the deployed backend API |
- PostgreSQL migration + live deployment (Render)
- PDF export of a completed DVIR (paper as fallback, not default)
- Photo attachments for damage markings
MIT