Automotive Dealer Assessment Platform
A dealer assessment and scoring tool that a global automotive client uses with its dealers around the world — evidence-backed grading, admin oversight, and role-based access, taken from development into live operation.
Full-stack developer — built on the founder/CEO's original MVP and carried it into live operation
Global automotive client
Oct 2025 – Jun 2026
React · TypeScript · Node.js/Express · MongoDB · JWT/RBAC
Client Project — Delivered at Learning Crew, for a global automotive client This work was done for a client under a confidentiality agreement. The client's identity, its assessment content and scoring rules, and all internal systems, data, and URLs are not shown. This write-up stays at the level of my role, the engineering decisions, and how I worked.
Overview
The platform is a diagnostic tool that a global automotive client uses with its dealers around the world. Dealers work through a structured assessment, attach supporting evidence, and receive an automatically calculated score and grade. An admin layer gives internal teams visibility across every dealer's results, and a super-admin console manages user accounts and role-based access.
The company's founder/CEO built the first working MVP. I joined as the full-stack developer and grew it from there: restructured the codebase, built out the assessment, scoring, reporting, and admin experience, hardened it, and took it from development into live operation — across an initial build phase and a later, spec-driven phase focused on stabilization and access control.
The Problem
An automaker running a global dealer network needs a consistent, repeatable way to understand each dealer's readiness — one that produces a defensible, evidence-backed result, reads the same way across every market, and can be reviewed by internal teams after the fact. The engineering challenge was turning a structured set of questions into exactly that, while the business rules behind the scoring kept evolving.
My Role
I was the full-stack developer on the platform throughout my involvement, working directly with the founder/CEO, who built the original MVP and continued contributing features of his own. This was collaborative work; everything described below as mine is work I built.
I worked remotely from India with the team in Korea on requirements, code review, deployment, and fixes, with working hours overlapping their office and a written update to the team at the end of every working day.
What I Owned
- Architecture — restructured the original single-app MVP into a client/server/shared monorepo, so business logic used by both sides lives in one place.
- Assessment workflow — the full multi-category, question-by-question flow, including draft autosave, evidence attachment, and the completion and grading flow.
- Scoring engine — designed and iterated a weighted scoring system through multiple rounds of changing business requirements.
- Dealer and admin experience — the dealer-facing assessment UI, dealer reports and history, and the admin dashboard (filtering, CSV export, per-assessment detail views).
- Authentication and RBAC — built the JWT-based authentication, then led a spec-driven initiative that added role-based access control and a super-admin user-management console.
- Testing infrastructure — introduced the project's automated backend test suite, including refactoring the server bootstrap so the app could be tested in isolation.
- Security hardening — input sanitization, tiered rate limiting, request validation, API-level security headers, and a startup check that refuses to run with a weak signing secret.
- Accessibility and responsive design — a dedicated, task-tracked pass: ARIA semantics, keyboard navigation, focus management, contrast fixes, accessible chart alternatives, and layouts fixed down to 320px screens.
Tech Stack
React 18 · TypeScript · Vite · Tailwind CSS · React Router v7 · Recharts
Node.js · Express · TypeScript · MongoDB (Mongoose)
JWT-based · role-based access control (dealer / admin / super-admin)
Jest · Supertest · in-memory MongoDB for isolated integration tests
Managed PaaS (static frontend + separate API service)
Architecture
The MVP was a single application, which is the right shape for proving an idea quickly. As the product grew, the first structural decision I made was splitting it into a monorepo with three packages: a client for the React SPA, a server for the Express API, and a shared package for types and business logic used by both sides.
Client — React SPA
Vite · TypeScript · dealer & admin UI
API Layer — Express
Modular route groups per domain · validation · sanitization · rate limiting
Shared Scoring Module
One module imported by both client and server
RBAC Middleware
dealer · admin · super-admin, enforced on the backend
MongoDB (Mongoose)
Document store for assessment data
Evidence Storage
Persistent across redeploys, fails loudly on misconfiguration
Key decisions:
- Modular REST API with a route group per domain, each with its own validation
- Role-based access control (dealer / admin / super-admin), enforced in backend middleware rather than trusted to the UI
- Shared business logic — scoring lives in a single module used by both client and server, so the score a dealer sees and the score that's stored can't drift apart
- Fail-loud storage — evidence storage resolves to persistent storage in production and logs an explicit warning if it can't, instead of silently writing to ephemeral disk
Key Features
- Assessment Workflow — Multi-category, question-by-question flow with draft autosave (local + server), evidence attachment per question, and a completion flow that locks in a graded assessment.
- Scoring Engine — Weighted scoring normalized into a grade, built to absorb repeated requirement changes. The client's weights, rules, and question content are confidential.
- Reports & History — Grade reports with category-level breakdowns, improvement suggestions based on score gaps, and a history view with date-filterable trend charts.
- Evidence Upload — File-type and size validation, a dedicated upload rate limiter, and durable storage.
- Admin Dashboard — Filtering, CSV export, and per-assessment detail views across all dealers.
- Super-Admin Console — User account management with role-based access, implemented against a written specification.
- Accessibility & Responsive Design — Keyboard navigation, ARIA support, focus management, and layouts fixed down to 320px; a Lighthouse benchmark tracked Performance ≥89 and Accessibility ≥95 on the pages tested.
- Testing — Backend integration tests with Jest, Supertest, and an in-memory database, introduced from zero.
Engineering Notes
Keeping One Rule Consistent Across Duplicated Logic
When a new question type was introduced that shouldn't count toward the score, the exclusion rule had to be applied everywhere a score was calculated — eight call sites across the client and server, covering both the "achieved score" and "maximum possible score" paths.
8 Call Sites
Exclusion rule applied across client + server scoring paths
1 Missed
server-side category calculation at save time
Symptom
an invalid (NaN) value was being stored as a 0% category score
I added the missing check and documented every call site as a checklist for future question-type changes. Consolidating scoring into a single shared module (see Architecture) then removed most of the duplication that made this bug possible.
Owning a Regression in My Own Security Work
My request-sanitization middleware was HTML-entity-encoding characters inside stored file paths (& → &), which broke evidence links. The bug was mine, introduced by my own hardening pass.
I wrote a URL-repair utility that decodes the encoded entities (including double-encoding), strips stray control characters, and restores the correct path; applied it going forward and through a one-off migration for records already saved; and covered it with tests.
Tracing One Symptom Through Every Layer
Uploaded evidence wasn't being reflected as "documented" in reports, even though uploads succeeded. Instead of one root cause, there were four small gaps, one per layer: the controller wasn't extracting the field, the service wasn't persisting it, the read query wasn't selecting it, and the frontend's draft-saving logic dropped it in two save paths.
I traced and fixed each one independently rather than stopping at the first plausible cause.
Designing Storage to Fail Loudly
Uploaded evidence had to survive production redeploys, where a container's local disk is wiped. I built a storage-path resolver with an explicit order of precedence that logs a loud warning in production if no persistent location is available — so a misconfiguration is caught immediately instead of silently losing data.
Impact
- Took the platform from development into live operation — used by the client with its dealers around the world.
- Delivered a spec-driven second phase — stabilization, then RBAC and the super-admin console — with every task tracked to completion against explicit acceptance criteria.
- Introduced automated testing to the backend and made the server testable in isolation.
- Raised accessibility and mobile quality with a dedicated pass verified down to 320px screens.
- Removed a class of scoring bugs by consolidating duplicated client/server logic into one shared module.
- 400+ commits across this platform and the internal HR platform combined.
Scope & confidentiality: This case study reflects my period of involvement, not the platform's current state. I collaborated with the company's founder/CEO, who built the original MVP and remained involved throughout. The client's name, assessment content, scoring rules, internal systems, data, and URLs are confidential and deliberately omitted.