Real-time race timing dashboard for the Nürburgring Nordschleife, built on top of a public live-timing feed. It renders a live leaderboard, class standings, sector and lap bests, race-control messages, pit/stint tracking and an animated track map — all updating in real time over a WebSocket.
Disclaimer n-tracker is an unofficial, fan-made project. It consumes a publicly reachable live-timing WebSocket endpoint that is not operated by, or affiliated with, this project, the Nürburgring, or any series organiser. The protocol was reverse-engineered for personal and educational use. Use it responsibly, respect the data provider's terms of service, and don't hammer the endpoint. n-tracker stores and redistributes nothing — everything is rendered live in your browser.
- Live leaderboard — positions, gaps, intervals, last/best lap, updating in real time
- Class standings & history — per-class ranking and position changes over time
- Best laps, best sectors & top speed — session bests with the car that set them
- Sector bests — live sector-time tracking
- Race control messages — flags, penalties and announcements
- Track flag state — green / yellow / code-60 / red, etc.
- Time-of-day clock — synced to the timing feed
- Pit & stint detection — derived stint lengths and pit activity
- Animated track map — car positions plotted on the Nordschleife layout
- Resilient connection — auto-reconnecting WebSocket client with exponential backoff and a live status indicator
- Next.js 15 (App Router) + React 19
- TypeScript
- Tailwind CSS
- Framer Motion for animations
- Multi-stage Docker build (Next.js
standaloneoutput)
- Node.js 22+
- npm
npm install
npm run devOpen http://localhost:3000.
Copy .env.example to .env.local and adjust as needed:
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_EVENT_ID |
50 |
The event ID to track on the live-timing feed. |
NEXT_PUBLIC_IMPRINT_URL |
(unset) | Optional URL for the "Impressum" footer link. Leave unset to hide the footer. |
cp .env.example .env.localnpm run build # production build
npm run start # serve the production build
npm run typecheck # tsc --noEmitdocker compose up --buildThe app is served on http://localhost:3000. The image is a minimal multi-stage build using Next.js standalone output; it runs as a non-root user and ships with a healthcheck.
app/ Next.js App Router entry (layout, page, global styles)
components/ UI components (leaderboard, track map, panels, …)
hooks/ useLiveTiming — connects the WS client to React state
lib/ WebSocket client, types, pit detection, track geometry, utils
The browser opens a WebSocket to the live-timing server, sends a subscription frame (eventId + topic IDs), waits for the time-sync handshake, then receives an initial snapshot followed by delta frames. lib/live.ts handles the connection and reconnection; hooks/useLiveTiming.ts reduces incoming packets into a single state object that the components render. See the protocol notes at the top of lib/live.ts.
MIT © Tim Goldbach