A full-stack Formula 1 prediction league built for serious race strategy fans.
F1 Predictor League lets players predict race outcomes, compete across a full season, track live timing, and review automated scoring after every Grand Prix weekend. It combines a game layer, live motorsport data, admin controls, mobile/PWA support, and Discord notifications into one working product.
Live app: f1-predictor-league.onrender.com
Related API: F1 Live API
Most fantasy-style sports games simplify the experience. This app is designed for users who understand race strategy, driver deltas, DNFs, sprint weekends, timing gaps, and constructor-level outcomes.
It is built as a working product, not a static demo:
- users can log in
- predictions can be submitted and locked
- scores can be calculated automatically
- live race data can be streamed
- admins can manage users and results
- the app can be installed on mobile as a PWA
| Area | What it does |
|---|---|
| Prediction engine | Driver, constructor, wildcard, sprint, and season-long predictions |
| Live timing | Real-time leaderboard, gaps, tyres, sectors, pits, weather, and race control |
| Scoring | Automated round scoring with penalties and season standings |
| Admin tools | VIP toggles, score management, prediction review, manual finalisation |
| Mobile/PWA | Installable mobile experience with responsive layouts |
| Notifications | Discord updates for deployment, reminders, and score breakdowns |
- Driver predictions for key finishing positions
- Constructor predictions based on combined driver results
- Wildcards for race and sprint movers
- Season predictions for WDC and WCC
- Strategy lockout before qualifying
- Opponent pick visibility after lockout
- Real-time leaderboard through SSE with polling fallback
- Tyre strategy and stint information
- Sector and mini-sector timing
- Pit stop feed
- Race control messages
- Team radio feed
- Connection status and reconnect handling
Tap any driver to inspect:
- telemetry
- timing
- strategy
- team radio
- Player league table
- F1 Drivers' Championship view with official rank/points
- F1 Constructors' Championship view with Race-only win counts
- 2026 race calendar
- sprint weekend detection
- session timing
- next-race countdown
- track intelligence and weather
- The app now uses the F1 Live API calendar as the source of truth for race/session timing.
- Static local schedule timings are no longer used as an automatic runtime fallback when the API and last-good dynamic cache are unavailable.
- Session aliases support both API and app naming styles, including
sprint_qualifying/sprintQualiandqualifying/quali. - Display round and timing archive round are preserved separately, so Miami can display as round 4 while using archive
apiRound6. /api/live/resultsmaps archive result files back to app display rounds for Past Sessions.- Season-long prediction locks now come from the dynamic first-race lock calculation instead of a hardcoded Australian GP Qualifying timestamp.
- The Standings tab receives official F1 rank/points with Race-only wins and podiums from the API.
- See API + App Ecosystem Flow for the full Mermaid data-flow diagram.
| Layer | Stack |
|---|---|
| Runtime | Node.js 18+ |
| Backend | Express |
| Database | Turso / libSQL |
| Auth | Google OAuth 2.0 + JWT |
| Live data | Custom F1 Live API using F1 timing feed |
| Frontend | Vanilla HTML, CSS, JavaScript SPA |
| Hosting | Render + Northflank |
| Notifications | Discord webhooks |
User browser / PWA
│
▼
Express web app
│
├── Auth and user sessions
├── Prediction submission and lockout logic
├── Scoring and admin controls
├── Turso/libSQL persistence
└── Discord notification layer
│
▼
F1 Live API
│
▼
Formula 1 live timing feedgit clone https://github.com/harsh779/f1-predictor-league.git
cd f1-predictor-league
npm install
node server.jsCreate a .env file before starting.
Required production-style variables:
| Variable | Description |
|---|---|
PORT |
Server port |
APP_URL |
Public app URL |
JWT_SECRET |
JWT signing secret |
TURSO_DATABASE_URL |
Turso database URL |
TURSO_AUTH_TOKEN |
Turso auth token |
GOOGLE_CLIENT_ID |
Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
Google OAuth client secret |
DISCORD_WEBHOOK |
Discord webhook URL |
F1_TIMING_API |
F1 Live API URL |
F1_TIMING_API_KEY |
Optional API key for live timing API |
API_SPORTS_KEY |
Optional weather fallback key |
npm testUseful commands:
npm run test:syntax
npm run test:smoke
npm run test:allManual smoke test:
- Open the app and confirm the home page renders.
- Check next-race card, lock state, and session timing.
- Log in and test prediction submission.
- Open live timing and verify available panels.
- Review past results and standings.
- Confirm Discord notifications if configured.
| Prediction type | Rule |
|---|---|
| Driver positions | Exact match: +2; off by N positions: -N |
| Constructor positions | Based on combined finishing positions |
| Wildcards | Correct pick: +5 |
| WDC prediction | Correct pick: +50 |
| WCC prediction | Correct pick: +25 |
| No submission | Lowest round score minus 5 |
| Incomplete submission | 5 points lower than lowest scorer |
DNF handling is built into the scoring logic so race incidents affect the prediction game meaningfully.
Live product. Actively improved across UI, scoring logic, admin tooling, race-data integration, and mobile experience.
Built by Harsh Khandelwal as a portfolio-grade product showing full-stack application thinking, sports analytics, live data integration, and AI-assisted product development.