Side project
Undercut
Motorsport predictions between friends, across a full season.
- Role
- Design and development
- Year
- 2026
Overview
Undercut grew out of a Discord bot I wrote for a community of 30,000+ people. The bot worked, but Discord was the ceiling: no real leaderboard page, no readable history, and every new scoring rule became yet another command. Moving to the web was the only way to grow the product.
I structured it as a Turborepo monorepo so types are shared between the client, the API and the bot. That is the decision that saved me the most time: when the shape of a prediction changes, typing breaks in all three places instead of breaking in production.
Scoring is the part that needs the most care. Race results arrive from the F1 calendar API, then a job scores each prediction against weighted rules: exact podium, race winner, fastest lap. The calculation is idempotent, so replaying a race never doubles anyone's points.
On the product side there is authentication, a friends system, seasonal leaderboards, and an admin back office to correct a result when the FIA revises a classification after the fact, which happens more often than you would think.
Highlights
- Turborepo monorepo: types shared across the client, the API and the Discord bot
- NestJS REST API with Prisma as the ORM, on a MySQL database
- BetterAuth authentication, friends system and seasonal leaderboards
- Integration of the official Formula 1 calendar API
- Continuous deployment through GitHub Actions, to Vercel (frontend) and Render (backend)
Stack
- TypeScript
- React
- SCSS
- Tailwind CSS
- NestJS
- Prisma
- MySQL
- BetterAuth
- Turborepo
- GitHub Actions
- Vercel
- Render
