F1 Atlas
Every season. Every race. Every driver.
What it is
F1 Atlas is a Formula 1 record book that spans every season from the first world championship in 1950 to the race that ran last weekend. You can follow a season round by round, open any grand prix for its full results and qualifying, track the drivers' and constructors' championships, explore a driver's season, or visit a circuit to see everyone who has ever won there.
Built in React, it has no backend of its own. Every screen is assembled live in the browser from the Jolpica API, which continues the long-running Ergast archive. No API keys, nothing stored, nothing running behind it.
The problem
The data is all there, but it comes back as an archive rather than a finished product, and three things stand between it and the race programme I wanted it to feel like.
First, the API paginates aggressively. Season results arrive a hundred rows at a time, which means a single race can be split across two responses. Second, it lags behind reality. The calendar knows a race has happened before the official results are published, leaving completed weekends with empty classifications for a day or two. Finally, it speaks in raw archive data. Drivers retire instead of recording a DNF, lapped cars lose their lap counts, and nothing looks like a Formula 1 timing screen.
The view I wanted most, a circuit's complete history of winners, doesn't exist as an endpoint at all. It had to be built from the raw data.
The decisions
Putting a split race back together
Season results are fetched a hundred rows at a time, using the first response to determine how many pages remain. If a race arrives split across multiple responses, the results are merged before they're displayed, so every grand prix appears as a single complete event.
Trusting the date, not the results
Whether a race is finished is determined by the calendar, not by whether the results have arrived yet. The morning after a grand prix, the site treats it as complete and simply leaves the podium empty until the official classifications become available.
Speaking the timing screen's language
Every finishing status passes through a formatter before it's displayed. Lead-lap finishers keep their gap to the winner, while everything else is translated into the abbreviations used on real Formula 1 timing screens.
| Archive says | Screen shows |
|---|---|
| Retired | DNF |
| Did not start | DNS |
| Disqualified | DSQ |
| Lapped | +1 LAP / +N LAPS |
| Anything unmapped | passed through as is |
Lapped cars have their lap count calculated from the winner's distance, while any unmapped status passes through unchanged so the table never ends up with blank values.
Building the circuit history the API doesn't provide
The API has no endpoint for a circuit's winners, so I built one from the data it does provide. By requesting only first-place finishes for a circuit across every season, I can reconstruct its history: how many races it has hosted, the years it spans, how many different drivers have won there, and who has won the most.
For Monza, that produces seventy-five races between 1950 and 2025, forty different winners, with Michael Schumacher leading the list on five victories.
What I'd do differently
The first thing I'd change is caching. Nothing is stored, so changing season re-runs every paginated request, and every circuit rebuilds its history from scratch. Since historical Formula 1 data rarely changes, caching previous responses would remove most of that work.
The second is driver photos. Podium headshots come from a fixed list of the current grid, so older seasons eventually fall back to three-letter driver codes. Driver pages already fetch portraits from Wikipedia, which covers almost every driver in the sport's history, so using that approach consistently would produce a much better result.
I know both improvements are there to make, and I deliberately left them. At some point, the honest decision is to stop chasing polish and call a project finished. For F1 Atlas, this was that point.