
Capabilities
- Leaderboards
- Back office
Frontend
Backend
DiRT Tracker
In ProgressDiRT Tracker came out of a living-room problem: a group of friends racing on one machine, one session open, wanting to log their times without signing in and out every run. It's a Next.js 16 app with Auth.js, Prisma and PostgreSQL, seeded with the game's real content.
The challenge
Shared spreadsheets fell apart fast: nobody remembered which stage, which car or which conditions a time was set under, so comparing was pointless. It needed a model that captured each run's context and a way to log someone else's time without handing over the session.
Implementation
The game's real catalog, seeded
The seed loads 13 locations, 156 stages and 79 cars with their data, and it's idempotent: rerunning it duplicates nothing and loses no already-recorded times.
Times with full context
Every entry stores weather, time of day, stage direction and input device (wheel or pad) alongside the car. Comparing a wet run on a wheel against a dry one on a pad stops being a pub argument.
Millisecond precision
Times are stored as whole milliseconds and formatted to MM:SS.mmm in the presentation layer, so leaderboards sort correctly and never drag floating-point errors around.
Mutations as Server Actions
Locations, cars, times, users and passwords are all modified through Server Actions validated with Zod and protected by session and admin-role helpers instead of per-route checks.
Forced password change on first login
Auth.js v5 with credentials and a JWT session; an edge-safe middleware redirects to the password change screen before letting anyone reach any other page.
Same schema locally and in production
PostgreSQL 16 in Docker for development and Neon in production, with the same Prisma migrations applied to both.