Changelog

Sector times no longer flicker when watching behind live

2026-10-03

After the spoiler fix, the S1/S2/S3 cells flickered when watching with a stream delay: a time would flash up for a moment, then vanish back to a dash. The cause was a timestamp inconsistency at the data provider: their standard feed marks every timestamp as UTC, but their live stream omits the timezone on some message types — and a timestamp without a timezone gets read as local time. For a viewer in central Europe that put every streamed lap record two hours in the past, where the spoiler guard considered the lap long finished and revealed everything; seconds later the standard feed corrected the record and the guard hid the values again, over and over. All timestamps without a timezone are now treated as UTC, so the two feeds agree and sector times tick in once, at the right delayed moment, and stay.

The timing table no longer spoils lap times when watching behind live

2026-10-03

Watching with a stream delay — say 47 seconds behind, synced to a TV broadcast — the cars on the map were correctly delayed, but the timing table showed each lap time the moment it was set, up to a whole lap before the delayed car crossed the line. Sector times leaked the same way, lighting up before the car had reached that sector. The cause: a lap's record is filed under the time the lap began and filled in as the car drives it, so any view of the past could see values from its future. Every timing value is now revealed only once the moment it describes has passed at the position being watched — the lap time when the car crosses the line, each sector as the car completes it, best laps and the qualifying order along with them. Replays reveal times the same way, so a replayed session now unfolds like the real one did.

Cars on the live map move smoothly instead of stuttering

2026-10-03

Car positions arrive from the data provider only two to three times a second, and the map was snapping each car to its newest known position and easing toward it — a visible lurch-and-stall several times a second, most obvious at racing speed where a car covers several lengths between updates. The map now looks at the position reports on either side of the moment being shown and places each car along the line between them, so it moves at its actual speed. Where the next report hasn't arrived yet — watching hard against the live edge — it falls back to the old behaviour rather than guessing where the car is heading, and it never draws a car drifting across a long data gap. Replays get the same treatment.

Gap column now works during qualifying

2026-10-03

The Gap column in the live timing table stayed empty for every driver throughout qualifying. It was built on the data provider's gap-to-leader feed, which only exists during races — in qualifying there is simply nothing to fetch. The gap is now calculated from what qualifying actually produces: each driver's best lap compared with the session leader's, shown as +0.000 behind the leader. Because the best laps already reset between Q1, Q2 and Q3, the gaps reset with them.

Live timing table no longer goes blank during sessions

2026-10-03

During live qualifying the timing tower could sit empty while the browser console filled with "Too Many Requests" errors. The cause: every viewer's browser asked the data provider for lap times, positions and track data separately, several times a second between them, and the provider allows only about three requests a second in total — so during a session, when it matters most, almost every request was refused. The server now fetches each kind of data once per interval and shares the answer with every viewer, so a hundred people watching costs the same as one. Three smaller failures made the outage worse and are also fixed: the gap-to-leader feed was being requested all through qualifying even though it only exists during races, with each refusal retried; the live streaming connection was silently cut by the hosting platform after a few minutes and never re-established, freezing lap times until the page was refreshed — it now reconnects on its own; and if the provider still refuses a request, the last good answer from the previous couple of minutes is shown rather than nothing.

Missing lap charts on 68 race pages, and empty winner lists on 5 circuits

2026-09-30

Checking over the search-engine work turned up three places where pages had been quietly shipping incomplete. Lap-time analysis was missing from 68 of the 85 race pages that should have it, five circuit pages listed no past winners at all — Interlagos alone should show 42 races — and every driver page displayed a name worked out from its web address rather than the real one. All three had the same cause: the site was requesting data from external sources while a release was being prepared, far faster than those sources allow, and the refusals were being quietly ignored, so whatever was missing got frozen into the page. Anything that cannot change — past race winners, driver biographies, the identifiers linking a race to its timing data — is now saved in advance and read from disk, so preparing a release makes almost no outside requests at all and finishes in seconds rather than minutes. Refusals are also no longer silent. One long-standing bug surfaced along the way: races in the USA, UK and UAE were never able to find their timing data, because the two sources spell those countries differently, so Silverstone, Miami, Austin, Las Vegas and Abu Dhabi had never shown lap charts.

Unknown drivers now 404, and every driver page shows the right name

2026-09-30

A made-up driver address like /drivers/not_a_driver answered with "Driver not found" but reported the page as perfectly fine, so search engines were free to index an endless supply of empty pages; those now return a real 404. Driver and circuit pages each carried their page title twice over, once in the top bar and once in the page itself, which leaves search engines guessing which one the page is actually about — the bar is now plain text. The main section headings on the Dashboard, Results, Drivers, Standings and Battles pages read as bare labels; they now match what each page is called. Chasing those changes turned up something worse: every driver page had been built with a name guessed from its web address rather than the real one, because the site was asking for 130 driver biographies while a build was running and the source refused most of them for asking too quickly. Biographies are now saved alongside the career records — they were already included in data being downloaded and simply thrown away — so nothing is requested during a build and names, nationalities and ages are correct everywhere, accents included. Builds went from roughly two minutes to under one as a result.

A Standings page, seasons with their own addresses, and driver-vs-driver pages

2026-09-30

Standings had no page of its own — they were a card on the dashboard that collapsed to ten rows, so the rest of the grid was only ever a click away and never in the page itself. There is now a Standings entry in the sidebar showing the complete drivers' and constructors' tables, with a page per past season back to 2020. Picking a season on Results or Battles used to change a query parameter rather than the address, which meant all seven seasons shared one link: nothing to bookmark, nothing to send someone. Each season now has a real address — and old links carry across rather than quietly showing the wrong year. Comparing two drivers was likewise trapped in a pop-up with no address, so a comparison could be looked at but never linked to; head-to-heads between teammates and between the championship's leading drivers now have pages of their own, while the pop-up still handles any other pairing. The comparison numbers and the Battles cards are now computed by the same code, so they can no longer disagree. Sharing any page also produces a proper preview card now, carrying the race winner, the driver's career totals or the circuit's lap record.

Every page now has its own title, and 170 of them are prerendered

2026-09-29

The site had around 300 pages of unique content — 146 race results, 130 driver careers, 24 circuit guides — and every single one of them told search engines it was called "F1 Stats" with the same one-line description, because only the root layout and the Battles page ever set any. Search engines collapse duplicate titles, so those pages were competing with each other as if they were one. There was also no sitemap, and the Drivers page only links the current season's grid, which left more than a hundred career pages with no route in from anywhere on the site. Each page now describes itself: a race page leads with its winner and podium, a driver page with seasons raced, wins and best championship finish, a circuit page with its length, corners and lap record. Every page declares a canonical address, ships structured data describing what it is — a race, a person, a place — and appears in a sitemap alongside the pages that previously had no links pointing at them. Race, driver and circuit pages are now built ahead of time rather than assembled on each visit, which is only possible because finished rounds were frozen into static data last week; they serve in single-digit milliseconds instead of around 130. Driver pages very nearly missed out: fetching live team colours was checking for stored credentials on every request, and that check alone is enough to rule a page out of being built in advance — even though the driver list needs no credentials at all. Requests for public data no longer ask for them.

Missing podiums on the season list, and a six-month-stale Battles page

2026-09-28

Several rounds on the Results page showed no podium at all — Suzuka, Barcelona and Silverstone among them — and the Battles and driver pages had been showing a one-race 2026 season since March. Both had the same root cause. The season list asked the results API for all 23 rounds at once, which trips its rate limit at around four requests per second; whichever four or five requests lost the race came back throttled and were quietly discarded, leaving gaps. The per-driver and teammate statistics were precomputed into a file that was generated once after Melbourne and never regenerated. Every request for F1 data is now queued and spaced so it cannot trip the rate limit, and retries when it does. More importantly, finished rounds are now frozen: once a race has run and settled for a day, its result and qualifying ship with the release as static data and are never fetched again. Anything not yet frozen — this weekend's race, a round newer than the release — is still fetched live, so a page visited the evening after a race shows that race. Teammate battles and per-driver season statistics are now derived from that round data on every request rather than read from a snapshot that goes stale the moment the next race runs.

Qualifying now shows which segment is running

2026-09-16

The qualifying header now carries a SEGMENT indicator reading Q1, Q2 or Q3, in the slot the lap counter occupies during a race. The segment was previously worked out by looking for "Q1"/"Q2"/"Q3" in race control messages, but the messages that actually bracket each segment are "SESSION STARTED" and "SESSION FINISHED", which contain none of those — the only messages that do are the stewards' incident reports, which arrive after the segment they name has already ended. The result read blank for the whole of Q1 and then lagged a full segment behind. It now reads OpenF1's qualifying_phase field directly. The same signal fixes the segment boundary used to reset Best and Last times between segments, so those reset exactly on the green light rather than on the previous segment's chequered flag, and a red flag inside a segment no longer risks wiping the times set before it.

Race control messages no longer appear two or three times

2026-09-16

Every race control message was listed more than once — twice during a race, three times in qualifying — so the message panel showed half as much actual news as it appeared to. Messages reach the app from three places (the live MQTT stream, the initial REST backfill, and the REST poll that runs every 10 seconds), and unlike lap records they were stored without any duplicate check, so each copy was kept. Messages are now recognised by their timestamp, category and text, and only the first copy is kept.

Live map keeps working when the MQTT stream is down

2026-06-14

Car positions on the live map were fed exclusively by the MQTT stream, so if the stream delivered nothing (an OpenF1 broker outage, or an account without MQTT streaming entitlement), the map stayed empty even though REST data was available. The live view now also polls car locations over REST (every 2s) as a fallback, so the map paints and cars move whenever live REST data is accessible — independent of stream health. Added an /api/debug/mqtt-probe endpoint that authenticates with the access token and reports whether the broker delivers any messages, to diagnose stream issues quickly.

Fixed live MQTT stream delivering no data (empty map, frozen timings)

2026-06-14

The live race stream connected but received no messages, so the map stayed empty and timings froze on the snapshot from page load. OpenF1's MQTT broker authenticates with the OAuth2 access token as the password (the same token used for REST) — the stream was connecting with the raw account password instead, which the broker accepts as an unentitled session: the subscription is granted but no live data is ever pushed. The stream now authenticates with the access token, restoring real-time car positions and live timing updates.

Starting grid on the dashboard once qualifying is done

2026-06-13

Once qualifying has run for the upcoming race (but before the race itself), the dashboard's Next Race card now shows the starting grid beneath the weekend schedule — compact, team-coloured driver pills in grid order, with pole highlighted. The top five are shown by default; a chip expands to reveal the full grid.

Live view no longer drops to the replay picker when a session overruns

2026-06-13

Qualifying and practice frequently run past their scheduled end time (red flags, incidents). The race page was deciding live-vs-replay from a hard scheduled-end comparison, so an overrunning session would suddenly switch to the "choose a replay" screen even while it was still running. The live view now stays up through a grace window past the scheduled end, and the live/replay mode is set explicitly by how you entered the page rather than re-derived. (If the page still shows the replay picker during a live session, that points to an expired OpenF1 token — check Settings → API credentials.)

Fixed qualifying timing tower freezing during final hot laps

2026-06-13

The qualifying timing board no longer goes blank/frozen while drivers complete the flying laps they started just before the chequered flag — often the fastest laps of the segment. The segment reset was treating the chequered flag as the immediate start of the next segment, which filtered out those still-completing laps (they start before the flag) until the next segment actually began. The board now keeps the ending segment active until a new lap is started after the flag, so Best, Last Lap, sectors, and the order keep updating live as the final laps cross the line.

Circuit pages now show the all-time fastest lap

2026-06-06

Each circuit now displays two distinct records: the all-time Fastest Lap (the quickest lap ever set at the current layout, almost always a qualifying lap) alongside the official Race Lap Record (fastest lap set under race conditions). Previously only the race lap record was shown and labelled simply "Lap Record", which was misleading — e.g. Monaco listed Hamilton's 1:12.909 race record but not Norris's all-time 1:09.954 from 2025 qualifying. All 24 circuits have been updated with verified data.

Reliable Q1/Q2/Q3 reset in the timing tower

2026-06-06

The qualifying timing tower now resets Best, Last Lap, sectors, and the running order between segments based on the chequered flag that ends each segment, rather than a lap-timing gap. This fixes cases where previous-segment times carried into the next, and it no longer resets mid-segment after a red flag.

Timing board stays fresh during live sessions

2026-06-06

Lap times, sectors, gaps, and running order now keep updating live without needing a page refresh. Previously the board only updated from the realtime stream, so if that connection dropped the data would freeze; it is now backed by lightweight polling so the latest timing is always shown.

Live sector times in the qualifying timing tower

2026-06-06

During qualifying, S1/S2/S3 and the speed trap now tick over live as a driver runs their current lap, and each sector is coloured against the field — purple for the overall fastest sector, green for a personal best. Rows stay blank until a driver completes their first lap of the segment, so the board no longer shows scattered partial sectors at the start of Q1/Q2/Q3. Joining a session mid-way now reliably backfills the segment’s best laps and running order — the lap history is re-fetched with retries if the first attempt comes back empty.

Collapsible sidebar

2026-05-24

Collapse the sidebar to icon-only mode to reclaim screen space. State is persisted across page reloads.

Qualifying timing tower resets between segments

2026-05-22

Best Lap, Last Lap, and the sort order in the timing tower now reset between Q1/Q2/Q3. Lap times from a previous segment are no longer carried forward.

Qualifying segment shown in header

2026-05-22

During qualifying, the session header now shows Q1, Q2, or Q3 based on race control messages, instead of just "Qualifying".

Lap data persists while driver is in the pit

2026-05-22

Last Lap, sector times, and speed trap now stay visible when a driver is in the pit — the timing tower shows their most recently completed lap instead of going blank. Best Lap column is also unaffected.

Best lap column in timing tower

2026-05-22

The timing tower now shows each driver's personal best lap time in a dedicated "Best" column, always visible alongside their last lap. The overall fastest lap is highlighted in purple.

Live race: play, pause, and scrub

2026-05-03

The live race view now uses the same playback controls as replay — play/pause, drag the timeline back up to 3 minutes into the buffer, then resume from where you paused. The Settings catch-up delay just sets the initial cursor position; once you're in the page you can sync to TV by scrubbing.

Debug page for OpenF1 connectivity

2026-05-03

New /debug page surfaces tier/credential state, runs every authenticated REST endpoint with status/latency/sample, and shows live MQTT message counts per topic — so an empty race view is no longer a black box.

Sidebar reflects live session state

2026-04-29

The race nav item now reads "Live Telemetry" with a pulsing red dot when a session is in progress, and "Replay Telemetry" without the dot otherwise.

Support the project

2026-04-29

Added a "Buy me a coffee" link in the sidebar footer for anyone who wants to chip in toward keeping the site running.

Mobile scroll fix

2026-04-29

Switched the app layout to use the dynamic viewport height unit (dvh) so iOS Safari no longer hides the top or bottom of the page behind the URL bar — no more double-scrolling on iPhone.

New SVG logo

2026-04-28

Replaced the placeholder text logo with a professional SVG mark featuring custom geometric F1 letterforms. The logo respects the team accent colour system and can be used at any size.

Live Race preview screenshots

2026-04-28

The Live Race gate now shows thumbnail previews of the map and pit stop visualization. Click either thumbnail to view it full size.

Merged Results & Standings

2026-04-28

The separate Standings page has been merged into Results. The Results page now shows a Drivers/Constructors toggle that switches the championship battle graph and standings table between both championships. Standings expand from 5 to all entries on demand.

Circuits page

2026-04-17

New Circuits section shows all 24 F1 tracks with statistics: circuit length, corners, DRS zones, race laps, lap record and first GP year. Click any circuit to see its full race winners history fetched from the Jolpica API.

Cancelled race weekend indicator

2026-04-16

Race weekends cancelled mid-season (Bahrain & Saudi Arabia) now show a strikethrough overlay with a "Race Weekend Cancelled" badge in the replay picker, and cannot be selected.

Grid → Finish bump chart revamp

2026-04-14

Replaced the hand-rolled SVG slope chart with a Recharts LineChart. The chart now scales responsively, shows an interactive sorted tooltip per column, and uses dashed lines for DNF drivers.

Championship Battle chart revamp

2026-04-14

Replaced the hand-rolled SVG championship chart with a proper Recharts LineChart. The chart now scales responsively, shows an interactive tooltip with driver codes and points, and includes a colour-coded driver legend.

Replay session picker

2026-04-14

When there is no live race, the race page now shows a grid of all completed races from the current season. Pick any race to load its full replay.

Race view loading sequence

2026-04-14

Live race view now shows a staged initialisation overlay — session info, stream connection, weather, race control, track status, driver timings, and telemetry each confirm as data arrives, then fade away.

Pit stop exit window on gap map

2026-04-07

Clicking a driver in circular mode now shows a green-to-red gradient arc spanning the full pit exit window — quick stop (−1s), median, and slow (+2s) — plus an inset card with projected rejoin gaps.

Current season results and qualifying

2026-03-29

The history page now shows race results and qualifying data for the current season. Race detail pages render qualifying even before the race has happened.

Fix replay timing tower empty stats

2026-03-28

Fixed race replay showing empty stats and position 99 for all drivers. Added retry logic and request staggering for session data fetching, response validation, and proxy error resilience.

Circular gap map with pit stop projection

2026-03-27

New circular map mode in the live race view shows cars on a circle with correct time gaps. Select a driver to see a ghost marker showing where they'd rejoin after a pit stop — useful for spotting traffic vs clear air.

Responsive circuit map

2026-03-26

The live race circuit map now dynamically fills all available screen space instead of rendering at a fixed size.

Multi-user credential storage

2026-03-26

API credentials are now stored in encrypted browser cookies instead of server-side files, enabling multi-user support on hosted deployments.

Lap time analysis — delta mode & fullscreen

2026-03-26

Lap time analysis now has a delta mode, inline gap-to-fastest in the tooltip, fullscreen view that fills the entire screen, and smoother curves.

Lap time analysis

2026-03-25

Compare driver pace lap-by-lap on any race result page (2023+). Select up to 4 drivers to see their lap times charted with tire strategy overlays. Toggle pit lap filtering for cleaner analysis.

Navigation overhaul

2026-03-25

Unified navigation across the app with reusable NavLink, NavPill, and BackButton components. Sub-pages now show a back button in the header bar for a native app feel. Dashboard standings cards expand inline with 'Show all', and driver rows link directly to profiles.

Driver profile pages

2026-03-24

Browse all drivers in the grid and view detailed profiles with headshot, current season stats, race-by-race results, career history, and progression charts.

Race replay playback

2026-03-10

Completed sessions now auto-enter replay mode with full playback controls — play/pause, speed (0.5x–16x), timeline scrubbing, and jump-to-time. All race data (positions, timing, flags, weather) plays back in sync.

Multi-season Battles page

2026-03-10

The Battles page now supports switching between seasons with a tab selector. 2026 data with Audi and Cadillac teams is included. The Compare modal adapts to the selected season.

Team color bars on Standings page

2026-03-10

The full Standings page now shows team color bars next to each driver and constructor, matching the dashboard style. The championship leader row is highlighted with their team color.

Add 24/12-hour clock setting

2026-03-09

Choose between 24-hour and 12-hour time format in Settings. The preference is saved and applied to all schedule times across the app.

Track time for race schedules

2026-03-09

Toggle between your local time and the track's local time on the next race schedule pills. Covers 30+ circuits with correct IANA timezones.

Improved race schedule pills

2026-03-09

Session pills now have color-coded borders — red for Race and Quali, amber for Sprint and SQ, and a subtle style for practice sessions.

Redesigned podium display

2026-03-09

Podium results on the dashboard and race detail pages now use a stacked row layout with position badges, team color bars, and driver names highlighted in team colors.

Biggest gainer icon in results

2026-03-09

The driver who gained the most positions is now highlighted with a trending-up icon in the race results table.

Enriched dashboard

2026-03-09

The dashboard now shows a next race countdown card, last race podium results, team color bars in standings, and championship point gaps.

Better history page UX

2026-03-09

Past races are now clearly clickable with a chevron icon, while future races are visually dimmed and non-interactive.

About page and disclaimer

2026-03-09

Added an About page with project info and data source credits. The live race view now includes a disclaimer about this being a hobby project.