Grand Prix 2026: Live Race Tracker
Broadcast-style motorsport dashboard with real-time car tracking.
Tip: click Fullscreen for the best experience.
What's on the page
It's a dashboard, not a game. Open it and it is already running: a countdown to the next race down to the second, the last race's winner and podium, a positions table, a canvas map of every car on track, all 22 rounds of the 2026 calendar, and both championship tables.
Read the build notes ↓About this project
A Grand Prix 2026 season dashboard with a live news ticker, race countdowns, standings, and the full calendar. Its centerpiece is a canvas Car Tracker that pulls live GPS telemetry from public racing APIs and animates every car around the circuit at 60fps, with graceful offline fallbacks.
Built with
How to use it
- Nav links. Positions / Car Tracker / Calendar / Standings
- Smooth-scrolls to that section of the page. Desktop only: the nav bar hides itself below 768px wide.
- Tab
- Steps through those same four links and puts a red outline on the focused one. They are the only focusable elements on the page.
- Scroll
- Each section fades and slides up once as it enters the viewport, then stops being watched.
- Swipe or drag sideways on a table
- The positions and standings tables scroll horizontally inside their panel when the screen is too narrow to fit them.
- Hover a race card or a table row
- The calendar card lifts 6px and its border turns red; table rows brighten under the cursor.
Build notes.
What's on the page
It's a dashboard, not a game. Open it and it is already running: a countdown to the next race down to the second, the last race's winner and podium, a positions table, a canvas map of every car on track, all 22 rounds of the 2026 calendar, and both championship tables.
Unofficial and fan-made. I have no connection to any commercial racing league, governing body or team. The whole thing reads public APIs, and there is a notice saying exactly that in the page's own footer, because the page is reachable on its own URL outside this site.
There is nothing to click except four nav links. I wanted something that tells you the state of the season in one scroll, with no buttons and no settings.
Where the numbers come from
Two APIs. Jolpica supplies the calendar and both standings tables; its URLs still have /ergast/ in the path because it is a drop-in replacement for the old Ergast API. the motorsport API supplies anything live: which session is running, the running order, and raw car coordinates.
Before either is called, the page renders a hardcoded snapshot dated 11 June 2026 in the source: 22 races, 22 drivers, 11 constructors, 20 finishing positions. So it is never blank. The live fetches then overwrite each section as they land, through Promise.allSettled, so a dead endpoint only takes down its own block.
One side effect I like. Driver standings from Jolpica get written into the same lookup table the canvas uses for colours, keyed by permanent number. The dot on the map and the row in the table are coloured by the same object.
Drawing a circuit I have no map of
There are no circuit outlines stored anywhere in this file. Not one SVG.
Instead I ask the motorsport API for one car's complete path through the session, every location sample for car number 12, and use that as the track. Take min and max on both axes, fit the box into the 900x520 canvas with 60px of padding and a 0.92 squeeze, and flip Y, because the API's Y grows upward and canvas Y grows down. Then two passes: an 18px faint backing stroke, and a 5px brighter line on top of it.
Two things went wrong. Gaps in the samples drew long straight lines slashing across the middle of the map, so now any jump over 600 units in the raw coordinates lifts the pen instead of joining. And re-stroking a few thousand points sixty times a second is wasteful, so the finished outline is grabbed once with getImageData and stamped back down with putImageData at the start of every frame.
Twenty dots, one sample a second
Position data does not arrive at 60fps, so the animation and the network had to become separate things.
Each car keeps two points, prev and next, each with a timestamp. The render loop works out how far through that gap the clock currently is and draws the dot at the interpolated spot: a 9-pixel-radius circle in the team colour, a 16-pixel glow behind it, the car number in white on top. That fraction is capped at 1.4, so a late sample lets the car keep drifting a little instead of freezing, without letting it run away.
The poller reschedules itself rather than sitting on a fixed interval. Each cycle it recomputes whether the session is live from its start and end times, then waits 1 second before the next fetch if it is and 30 if it is not. Leave the tab open through a session start and it speeds up on its own.
Rough edges worth knowing about
The best time to look is during a session. Otherwise session_key=latest returns the last one that finished, so you get a real circuit drawn from real data with the cars sitting where they were in its final seconds. Still worth opening, because that is when you can watch a circuit's shape assemble itself out of nothing but coordinates.
Things I know are approximate. The countdown assumes every race starts at 13:00 UTC, which suits Europe and is wrong for a night race. The calendar and standings are fetched once on load and never refreshed; only the positions table, every 30 seconds, and the car map keep polling. The strip along the top is four lines the page writes about itself at load. The Last Race card in the hero is still plain markup: the IDs sit there waiting for a fetch I have not written yet. And if the browser blocks the cross-origin request, the motorsport API calls fall back through two public proxies before giving up.
On a phone under 768px wide the nav bar and the colour legend hide themselves, and the tables scroll sideways under your thumb.