What the product covers
A kart track is an operation with a fleet, a schedule and a queue of people at the desk. The platform was built around that whole loop instead of around the booking form:
- Admin dashboard for the track: fleet and karts, maintenance records, tracks and layouts, championships and sessions, and the people who drive.
- Driver experience on web and mobile: profile, history, bookings and the app used on race day.
- Agenda and bookings, with rental sessions modelled separately from championship rounds, because the two behave differently.
- Operational check-in at the desk, with a QR code and a boarding pass for the driver.
- Race control: blocking a driver and logging an incident, so a session can be managed while it is running.
- Financial dashboard for the track owner.
- Security layer for staff accounts: TOTP MFA, rate limiting, audit log and session timeout.
- WhatsApp agent, added later, for the questions that arrive by message instead of by screen.
How it is put together
One Turborepo monorepo, because web and mobile are the same product on different surfaces and
the rules have to be written once. apps/web is the Next.js 15 App Router
application (admin dashboard, driver portal and landing page), apps/mobile is the
Expo Router app for iOS and Android, packages/api holds the tRPC routers with the
business logic, and packages/db holds the Prisma schema and client.
Which part is mine
Built with one other developer. My part of it was the registration flows, the booking flow, the mobile app and the security layer:
- Registration: the whole flow, from the form to the record a championship field or a booking is built from, including the pilot code, the category and the data the track keeps.
- Bookings, for the rental sessions and for the championship rounds.
- The mobile app, the Expo and React Native side used on race day, including biometric login.
- The security layer: TOTP MFA, rate limiting, audit log and session timeout.
Technical decisions and trade-offs
- tRPC with Zod instead of a hand-written REST contract. Both clients call the same procedures and inherit their types, so web and mobile cannot drift apart. Trade-off: there is no public API surface, so a third party would need one built for it.
- Supabase for identity and Postgres, Prisma for the schema. One provider for auth and data, with the schema as code and migrations in the repository. Trade-off: the data layer leans on one vendor, and Prisma sits between the queries and the database.
- Biometric login on mobile, Google OAuth plus email on web. Staff at the desk open a browser; drivers open an app with a fingerprint. Same identity, two entry points.
- Playwright acceptance tests against a real Supabase instance instead of mocks. Trade-off: heavier and slower than unit tests, but they exercise the flows the way the track actually uses them.
- Docker Compose for the local stack (Supabase plus web), so the two of us ran the same environment instead of two similar ones.
Where it stands
The platform is deployed on Vercel with GitHub Actions and holds about 400 commits between the two of us. Live timing and results are the parts still on the roadmap; the rest of the operation runs on what was shipped.