Interactive Formula 1, F2 & F1 Academy race analytics — powered by real telemetry data.
📖 Project Wiki · 🌐 Live Site · ✨ Features · 🛠 Tech Stack · 🚀 Getting Started · 📄 License
Explore the intensive project wiki for in-depth documentation, technical architecture, and developer insights.
⚠️ Important Note regarding Live Data: The primary OpenF1 proxy authentication used in the Live Dashboard is restricted to the Cloudflare Worker deployed for the live site. If you clone and run this app locally, it will automatically fall back to the publicapi.openf1.orgendpoint — you can still use the dashboard seamlessly, though some high-bandwidth or live telemetry features may be restricted or rate-limited due to public API limits.
F1-Telemetry is an interactive web application built for motorsport fans who want to go deeper than the broadcast — providing detailed race analytics, real-time telemetry visualisation, multi-season driver & constructor statistics (/stats), driver comparisons, and a 3D race viewer across Formula 1, Formula 2, and F1 Academy. It also fully integrates the Formula1-Live dashboard for real-time live timing, track limits, and race control monitoring.
Attribution — Data is powered by the official OpenF1 API and Jolpica API.
New Features:
- Driver & Constructor Stats (
/stats): Deep multi-season (2018–2026) F1 statistical hub featuring livery-styled hero cards, career & sprint breakdowns, teammate head-to-head comparisons, lap-by-lap tyre/pit/weather analytics, constructor title histories, Team Principal / CEO timelines, and Power Unit supplier lineages. - Procedural 3D Tracks: The 3D Telemetry Viewer automatically generates accurate, rotating 3D track geometries from real GPS telemetry data, complete with dynamic racing lines, kerbs, and surrounding environments using React Three Fiber.
| Feature | Description |
|---|---|
| Driver & Constructor Stats | Multi-season (2018–2026) F1 stats (/stats) with career & sprint totals, teammate head-to-heads, PU & TP/CEO history |
| Race Leaderboards | Comprehensive race results with position changes, intervals and gap analysis |
| Lap-Time Analysis | Lap-by-lap performance metrics for studying consistency and strategy |
| Tire Strategies | Visual breakdown of compound choices and stint lengths across the grid |
| Fastest Laps | Highlights of the quickest laps set during each session |
| Pit Stop Analytics | Scatter-chart visualisation of pit-stop durations per driver |
| Driver Comparisons | Head-to-head telemetry overlays for any two drivers in a session |
| 3D Telemetry Viewer | Follow drivers around the circuit in a synchronised 3D scene with multiple broadcast-style camera angles |
| Procedural Tracks | Automatically generated, accurate 3D track geometries from GPS data with dynamic kerbs and environment |
| Interactive Calendars | Up-to-date 2026 schedule and 2027 preview schedule, linking seamlessly to circuit telemetry |
| Future Preview Mode | Graceful fallback rendering 3D circuits and metadata for future races when telemetry is unavailable |
| Live Dashboard | A fully integrated, real-time live telemetry dashboard (formerly Formula1-Live) with race control feeds |
- Admin Dashboard Improvements: We are continually refining the new internal developer dashboard (
/admin) for seamlessly updating all telemetry data (F1, F2, F1 Academy) via a UI. Future updates will add automated validation and deeper scraping controls.
| Layer | Technologies |
|---|---|
| Framework | React 19 · Vite 8 · React Router 7 |
| Styling | Tailwind CSS 4 · Sass (SCSS) · Flowbite React |
| 3D / Graphics | Three.js · @google/model-viewer · Tween.js |
| Data Viz | Recharts · D3.js |
| Animation | Framer Motion · Lottie |
| Backend / API | Local PHP Gateway (api.php) · Node.js Proxy |
| Tooling | PWA (vite-plugin-pwa) · Sitemap generation · SVGR |
- Node.js ≥ 18
- npm ≥ 9
- Python ≥ 3.9 (only needed for the
/admindata update buttons) — python.org/downloads
# Clone the repo
git clone https://github.com/your-username/F1-Telemetry.git
cd F1-Telemetry
# Install everything: frontend, backend AND the Python .venv
# (requirements.txt + Playwright Chromium are installed automatically)
npm install --legacy-peer-deps
# Start the dev server
npm run devIf Python wasn't installed when you ran
npm install, install it and then runnpm run py:install. If an admin update ever fails withModuleNotFoundError, runnpm run py:installand restartnpm run dev.
The app will be available at http://localhost:3006 (or the port shown in your terminal).
npm run build
npm run preview # preview the production build locallyProcedural Tracks (React-Three-Fiber)
F1-Telemetry features dynamic, procedural 3D tracks powered by Three.js and @react-three/fiber.
-
Downloading / Regenerating Track Data: Run the automated downloading script to pull single-lap spatial telemetry from OpenF1 for all 2026/2025 calendar circuits:
node scripts/downloadAllTracks.js
This creates clean single-lap coordinate data in
public/trackdata/<canonicalId>.json(such asmadrid.json,monaco.json,silverstone.json), trimmed to avoid multi-lap overlap. -
3D Geometry & Curvature Math (
src/utils/TrackBuilder.js):- Raw X/Y telemetry positional coordinates are smoothed using a moving-average filter and fitted to a 3D Catmull-Rom spline (
THREE.CatmullRomCurve3). - Apex & Corner Detection: Peak curvature calculations automatically locate circuit apexes and dynamically drop corner labels. This robust system falls back to automatic detection for new circuits (like Sepang during OpenF1 API testing) or enforces manual fraction mapping for specific tracks.
- Track Orientation & Calibration: Supports dynamic axis inversions (e.g.,
invertYfor Sepang) to correctly align raw GPS telemetry streams with standard 16:9 official broadcast track maps. Telemetry coordinates for driver dots are synchronized perfectly with the flipped geometry viatelemetryToScene. - Ribbon Geometry: Triangulates extruded 3D track ribbons with dynamic width, elevated curbs, sector color coding (Sector 1 red, Sector 2 blue, Sector 3 yellow), and dynamic start/finish line markers.
- Environment Scatter: Instanced low-poly tree assets (
InstancedMesh) and grandstand geometry are procedurally placed along track perimeters using normal vector math offsets.
- Raw X/Y telemetry positional coordinates are smoothed using a moving-average filter and fitted to a 3D Catmull-Rom spline (
-
Component Integration:
ProceduralTrackBackground: Rotates 3D tracks seamlessly as ambient backdrop headers.MiniTrackViewer&TrackModel: Provide interactive OrbitControls and modal 3D track visualization.
Transparent Video System (Luma Key)
Videos use a custom Luma Key pipeline for cross-browser transparency:
- Videos are encoded in a side-by-side layout — left half = RGB, right half = alpha mask.
- The
LumaKeyVideocomponent composites both halves onto a<canvas>at runtime.
Generate a side-by-side asset from a PNG sequence:
& "node_modules/ffmpeg-static/ffmpeg.exe" -y -i "input_%05d.png" `
-filter_complex "[0:v]pad=w=iw:h=ceil(ih/2)*2,split[v1][v2]; [v2]alphaextract[alpha]; [v1][alpha]hstack" `
-c:v libx264 -crf 18 -pix_fmt yuv420p "output.mp4"The
padfilter ensures the height is divisible by 2 for H.264 compatibility.
Driver Image Background Removal
Remove backgrounds from F2 driver headshots for a consistent look:
npm run remove-f2-bgTo process a different directory, edit the dirs array in scripts/remove-backgrounds.mjs.
Uses @imgly/background-removal-node for automatic detection.
Local Decoders
Draco and Meshopt decoders are bundled locally in public/decoders/ to bypass browser Tracking Prevention and ensure 100 % reliability.
World & Constructors' Champion Badges (src/config/champion.js)
F1-Telemetry displays animated crown badges (ChampionBadge) on F1 driver headshots, team garage cards, constructor standings, landing page podiums, and social media graphics. Everything is controlled from a single configuration file: src/config/champion.js.
-
Season Champions (
CHAMPIONS&CONSTRUCTOR_CHAMPIONS): Lists confirmed title winners by season. Badges only appear when viewing the matching season (e.g., a2026champion shows "2026 Champion" on2026pages and never leaks onto2025or older seasons):export const CHAMPIONS = [ { code: "ANT", name: "Kimi Antonelli", year: 2026 }, // no theme = gold { code: "NOR", name: "Lando Norris", year: 2025 }, { code: "VER", name: "Max Verstappen", year: 2024 }, { code: "VER", name: "Max Verstappen", year: 2023 }, ]; export const CONSTRUCTOR_CHAMPIONS = [ { teamId: "mclaren", name: "McLaren", year: 2025 }, { teamId: "mclaren", name: "McLaren", year: 2024 }, { teamId: "red_bull", name: "Red Bull", year: 2023 }, ];
-
Reigning Champions (
REIGNING_CHAMPION&REIGNING_CONSTRUCTOR_CHAMPION): Displays a "Reigning Champion" / "Reigning Constructors' Champions" badge during the following season (reigningSeason):export const REIGNING_CHAMPION = { code: "NOR", name: "Lando Norris", year: 2025, // Season the title was won reigningSeason: 2026, // Season they carry the Reigning Champion badge theme: "ice", }; export const REIGNING_CONSTRUCTOR_CHAMPION = { teamId: "mclaren", name: "McLaren", year: 2025, reigningSeason: 2026, theme: "ice", };
Set either object to
nullto hide the reigning badge, or updatecode/teamId,year, andreigningSeasonwhen a new season begins. -
Badge Themes: Omit
themefor the default gold crown, or settheme: "ice"for the ice-blue reigning styling (additional themes can be added insrc/components/ChampionBadge.css).
API Data Update Scripts (F1, F2 & F1 Academy)
Self-Contained Data Architecture
All generated JSON configuration and data files are stored directly inside this repository under src/config/. The production API seamlessly serves these files directly from this repository, meaning the project is entirely self-contained and no longer requires separate external data repositories (such as f1-telemetry-api, f1aapi, or f2api).
The project includes Python scripts that fetch the latest season data and format it into the local JSON config files:
- F1:
src/config/f1/api_update.py— Fetches data from the Jolpica API and OpenF1 API. - F2:
src/config/f2/api_update.py— Scrapes F2 results directly from the official FIA Formula 2 website. - F1 Academy:
src/config/f1a/api_update.py— Scrapes F1 Academy results directly from the official F1 Academy website. - Manually Updating
npm run update:f1runs F1api_update.pynpm run update:f2runsapi_update.py,format.py, andscrape_standings.pynpm run update:f1arunsapi_update.pyandformat.pynpm run update:cacherunsscripts/build-cache.mjsto rebuildpublic/stats_cache/for/statsnpm run update:allruns all four in order (update:f1,update:f2,update:f1a,update:cache)
Prerequisites
- Python ≥ 3.9 on your PATH (
py,python3orpython) - Python packages are listed in
requirements.txt(requests,numpy,playwright). They're installed into a project-local.venvautomatically bynpm install, or manually with:
npm run py:installThe backend and the npm run update:* scripts always use .venv when it exists, so your global Python is never touched. Override the interpreter with the PYTHON_CMD env var if needed, or set SKIP_PYTHON_SETUP=1 to skip the Python step during npm install (e.g. CI).
Updating Data via Admin Dashboard
All Python data-fetching scripts can now be executed seamlessly through the local Admin Dashboard, eliminating the need to manually run them in the terminal.
- Ensure your local dev server is running (
npm run dev). - Navigate to the
/adminroute in your browser (e.g.,http://localhost:3006/admin). - From the dashboard, you can execute the F1 Data update and Stats Cache (
build-cache.mjs) rebuild with a single click. - For F2 and F1 Academy, simply paste the official race URL into the input field and click update. The dashboard handles the argument passing and working directories for you!
Data Formatting
All results.json files are strictly formatted to maintain a highly compact, readable structure with exactly one line per driver.
- F1: Handled natively using a custom
write_compact_race_json()function. - F2 & F1 Academy: Requires a secondary
format.pyscript. The Admin Dashboard chains this automatically, but you can also manually run it by navigating tosrc/config/f2orsrc/config/f1aand runningpy format.pyin your terminal.
What it updates
| File | Description |
|---|---|
results.json |
Race results for every completed round |
qualifying.json |
Qualifying session results (Q1 / Q2 / Q3 times) |
sprint.json |
Sprint race results (sprint weekends only) |
races/races.json |
Race calendar with meeting keys |
races/{year}/driverStandings.json |
Cumulative driver standings after each round |
races/{year}/constructorStandings.json |
Cumulative constructor standings after each round |
drivers/ |
Per-driver career statistics and analytics |
constructors/ |
Constructor and driver rosters |
Note: The script includes automatic retry logic with exponential back-off for rate-limited (429) API responses. A full update run may take a few minutes depending on how many rounds have been completed.
Driver & Constructor Stats Hub (/stats & public/stats_cache/)
The /stats page (src/pages/Stats/) provides multi-season (2018–2026) F1 Driver and Constructor analytics (DriversTab.jsx, ConstructorsTab.jsx, StatsPage.jsx) backed by prebuilt static JSON files in public/stats_cache/ so the live site loads with minimal live API calls.
-
Static Cache Architecture:
public/stats_cache/{season}/season.json— Season standings, race results, qualifying, and sprint results (2018–2026).public/stats_cache/{season}/{round}.json— Per-race lap-by-lap stats, tyre stints, pit stops, and weather summaries.public/stats_cache/career.json— Aggregated driver career totals (starts, wins, podiums, poles, sprints, points, championships).
-
Rebuilding the Stats Cache:
- Via UI: Click Run build-cache.mjs in
/admin(supports optional season year and--force,--no-openf1,--no-careerflags). - Via CLI:
npm run update:cache # current season node scripts/build-cache.mjs 2025 # specific season node scripts/build-cache.mjs --force # rebuild already-cached races node scripts/build-cache.mjs --no-openf1 # Jolpica data only (skip tyres/weather) node scripts/build-cache.mjs --no-career # skip updating career.json
- Powered by
scripts/build-cache.mjsandscripts/cache-lib.mjs, and run automatically every Monday by.github/workflows/f1-update.yml.
- Via UI: Click Run build-cache.mjs in
OpenF1 API Rate Limiting (429) Mitigation
To ensure uninterrupted telemetry viewing during periods of high OpenF1 API traffic, several client-side strategies have been implemented to reduce and handle 429 Too Many Requests errors:
- Exponential Backoff Retries: Core API calls utilize an automatic retry queue starting with a 1500ms delay, doubling on each subsequent 429 response (up to 7 retries).
- Stale Cache Fallback: The persistent
localStoragecache handles API outages gracefully. If a network request fails (including terminal 429s), the application will fall back to expired cache data instead of breaking the UI. - Paced Pagination: Bulk data fetches bypass standard 500-record limits by paginating via timestamps, explicitly injecting a 300ms delay between batch requests to prevent rate limit spikes on the OpenF1 servers.
Hybrid API Proxy Environment
F1-Telemetry features a fully decoupled, hybrid API backend to ensure permanent stability even if external bespoke APIs are taken offline:
- Local Development: Running
npm run devstarts both the Vite frontend and a local Node.js Express server (backend/server.js) connected to a SQLite caching database.backend/database.sqlite: The primary development and administrative cache. It stores JSON responses from external APIs (Jolpica, OpenF1) to facilitate local testing and the data export workflow. While not used at runtime in production, it is essential for rebuilding the static datasets that the live site relies on.database.sqlite(root): A legacy or baseline cache file. It is not used in the current production runtime and primarily serves as a historical reference or remains from earlier project structures.
- Production Server: When built for production, the Vite code automatically switches routing to a native
api.phpfile, which seamlessly caches and routes data directly on IONOS Shared Web Hosting via file-based storage.public/api_cache/: The production caching directory. It stores API responses as static files to ensure the live site remains fast and stable even if external data sources are unavailable. This directory is excluded from version control.
Content Security Policy (CSP)
To enhance application security and mitigate Cross-Site Scripting (XSS) attacks, a strict Content Security Policy (CSP) is implemented.
Key aspects of our CSP configuration:
- API Endpoints: Explicitly whitelists connections to authorized data sources including the OpenF1 API (
api.openf1.org), Jolpica API (api.jolpi.ca), OpenWeather API, and GitHub Raw Content. - Assets & Media: Restricts image and media loading to the application origin and verified third-party providers (e.g., Flagpedia for driver flags).
- Scripts: Restricts script execution to the application origin, preventing unauthorized external scripts from running while allowing trusted analytics providers.
- Enforcement: Depending on the hosting environment (e.g., IONOS or Cloudflare), the CSP headers are actively enforced at the proxy/edge layer to ensure all browsers securely enforce the policy without manual intervention.
F1-Telemetry is deployed as a static site on IONOS. Key deployment notes:
- The
.htaccessinpublic/must be deployed at the web root to enable Gzip compression for.glbfiles. - The
public/decoders/folder must be included in the build output to avoid cross-domain script blocking. - Ensures that the
public/api.phpendpoint transfers cleanly to your root build directory structure. This PHP file functions as the dedicated caching layer and API proxy when hosted on IONOS Web Hosting Plus.
This project pulls data from four sources:
- OpenF1 API — Real-time and historical telemetry, track positioning, and stint data.
- Jolpica API — Custom local backend parser fetches F1 historical Race results, Driver Standings, and Constructor Standings directly from the reliable Jolpica API framework.
- OpenWeather API — Weather data.
- Internal Gateway (
api.php) — A custom auto-caching proxy that seamlessly fetches all configuration and data files for F1, F2, and F1 Academy directly from this self-containedF1-Telemetryrepository, fully eliminating the need for external data repositories.
- Development & AI Collaboration: This project is actively developed by Matthew Delong, in extensive pair-programming collaboration with Antigravity, an agentic AI coding assistant developed by Google DeepMind.
- Special thanks to data providers and API service OpenF1 that enable access to current and historical F1 data.
- Flagpedia — High-quality country flag WebP images used for race locations and driver nationalities.
- This work is based on "basic Lowpoly F1 Car V1" by arthihalder, available under a Creative Commons Attribution 4.0 International license. View the model on Sketchfab. License details can be found at CC-BY-4.0.
This project is available under the MIT License.
F1-Telemetry is an unofficial fan project and is not associated with Formula One companies. F1, FORMULA ONE, FORMULA 1, F2, FORMULA 2, FIA, FIA FORMULA 2 CHAMPIONSHIP, F1 ACADEMY, FIA FORMULA ONE WORLD CHAMPIONSHIP, GRAND PRIX, and related marks are trademarks of Formula One Licensing B.V.
