DEV Community

Nilamadhab Senapati
Nilamadhab Senapati

Posted on • Originally published at nilamadhab-coder.dev

I Resurrected a Dead F1 Project and Accidentally Built a Race Intelligence OS

GitHub β€œFinish-Up-A-Thon” Challenge Submission

This is a submission for the GitHub Finish-Up-A-Thon Challenge


What I Built

I built F1 Intelligence Studio β€” a full-stack Formula 1 race intelligence dashboard that turns raw telemetry data into a living, breathing visualization of any race from 2024 to 2026.

Think of it as a race engineer's war room. Twenty animated cars chase each other around circuits drawn from real GPS telemetry. An AI race engineer (Claude) analyzes strategy in real-time. A spring-physics camera zooms into wheel-to-wheel battles like an actual broadcast. ElevenLabs voices the commentary. A strategy simulator answers F1's eternal question: pit or stay out?

You can scrub through any moment of any race with frame-perfect precision. You can compare two drivers' telemetry traces side-by-side, watch tyre stints unfold, monitor team radio, and get AI-powered insights on developing battles.

It started as a single API call dumping data into a table. It ended as a 12-panel drag-and-drop dashboard with twelve interactive components. Somewhere in between, I lost track of where the line was β€” and that's the whole point of this story.

What this project means to me: It's the first side project I've actually shipped in years. My GitHub is a graveyard of half-built ideas. This one made it out alive.


Demo

🏎️ Live Demo: https://raceosf1.one/
πŸ“¦ GitHub Repo: https://github.com/nilamadhab47/raceosf1

Quick screenshots:

🟒 The animated track map with 20 cars on a real telemetry-derived circuit

animated track
🟒 Telemetry comparison β€” two drivers, speed/throttle/brake overlaid on the same distance axis

Telemetry comparison

🟒 The AI insights panel β€” Claude analyzing strategy in real-time and Strategy simulator showing pit vs stay-out delta

The AI insights panel

The Stack:

  • Frontend: Next.js 14, TypeScript, Zustand, GSAP, Recharts, react-grid-layout
  • Backend: FastAPI (Python 3.12), FastF1, WebSocket broadcasting
  • AI: Anthropic Claude (race insights + chat), ElevenLabs (voice commentary)
  • Infrastructure: Vercel (free tier) + Railway ($5/month)

Total infrastructure cost: less than my monthly coffee budget. The spring-damper camera system took more math than my engineering degree.


The Comeback Story

Here's the honest version.

My GitHub looks like a graveyard. Landing pages with no backend. ChatGPT chats about apps that never left the chat. Ideas rotting in a documents folder. I'm a full-stack engineer who builds production systems for a living β€” but my own projects? Couldn't finish a README.

The F1 project was no exception. I started it months ago when Instagram served me a dev reel about FastF1, that incredible Python package for Formula 1 telemetry data. My brain did its usual thing: "Oh that's cool, I should build something." I made a repo. Wrote a few API endpoints. Got driver data into a table.

Then? Procrastination. The classic excuses kicked in:

  • "Who's going to use this?"
  • "There's no monetization."
  • "You're a backend engineer pretending to do frontend."

The repo sat there for weeks. Untouched. Just another tombstone.

What changed:

I made myself one rule. Sit down after work. Fifteen minutes minimum. No "let me plan the architecture first" (the ultimate procrastination disguise). No "I'll start fresh on Monday." Just open the laptop and ship one small thing.

The beginning was ugly. Just ugly. But I kept showing up.

Then the escalation started:

  • Week 1: Tables turned into graphs. Slightly less boring.
  • Week 2: Graphs turned into driver comparisons. Wait, this is actually interesting.
  • Week 3: Comparisons turned into full race simulations. Now I need actual circuit maps?
  • Week 4: Drawing SVG tracks from raw GPS telemetry. I googled "what is a viewBox" at 11pm. No shame.
  • Week 5: Twenty animated cars chasing each other at 60fps. Bypassed React's render cycle entirely because setState 60 times a second is a war crime.
  • Week 6: Added an AI race engineer. Then voice commentary. Then a spring-physics camera that zooms into battles like an actual TV broadcast.

I looked up from my keyboard and realized what started as "let me show F1 data in a table" had turned into a complete Race Intelligence Operating System. My scope creep could lap Verstappen.

The finish-up grind:

When this challenge dropped, the project was mostly working but full of rough edges β€” the kind of rough edges that keep you from actually showing it to anyone. The "I'll polish it later" backlog. Sound familiar?

Here's what I cleaned up for the final push:

  • Documentation. The README was a single sentence. Now it's a proper onboarding doc with setup, architecture diagrams, and contribution guidelines.
  • Error boundaries on every panel. Before, one panel crashing could take down the whole dashboard. Now each panel fails gracefully on its own.
  • Loading skeletons. Previously the dashboard flashed empty boxes during data fetch. Now everything has proper loading states.
  • The YouTube content-ID disaster. F1 videos kept showing "Video unavailable" in production because FOM blocks third-party embeds. Built a three-tier fallback: Dailymotion β†’ non-blocked YouTube β†’ thumbnail cards with external links.
  • Deployment. Three Dockerfile failures on Railway. Path resolution, build context, and the infamous $PORT variable not expanding because Railway's startCommand doesn't run through a shell. Finally got everything green.
  • Polish pass. Onboarding tour, keyboard shortcuts, mobile-responsive grid presets, dark mode that doesn't look like an afterthought.

The before-and-after gap is the difference between "a thing on my laptop" and "a thing I can show people without apologizing."

The biggest lesson wasn't technical. It's that the beginning lies to you. It whispers "this is pointless" and "you're not good enough" β€” and if you listen, you add another repo to the graveyard and open Instagram instead.

The only answer is to keep showing up. Fifteen minutes at a time.


My Experience with GitHub Copilot

I used Copilot heavily during the finishing-up phase, and honestly? It's where it shined the most.

The interesting thing about reviving an abandoned project is that the fun parts are already built. What's left is the unsexy stuff β€” polish, edge cases, drag-and-resize logic, design system consistency. Things I'd normally rage-quit before finishing. This is exactly where Copilot earned its keep.

Where Copilot genuinely helped:

🟒 Drag-and-resize architecture for the dashboard panels. This was the single biggest unlock. I needed every panel to be draggable, resizable, and auto-adjustable based on its container β€” without breaking the internal components inside each one. Copilot helped me architect the layout system and walked through how to wire react-grid-layout with my existing panel components. The hardest part was making sure that resizing didn't break the SVG track map, the Recharts graphs, or the WebSocket-driven animations inside. Copilot suggested the right patterns β€” ResizeObserver for container-aware children, debounced resize handlers, key-based remounting for stubborn charts β€” without me having to re-architect each panel from scratch.

🟒 Type definitions for FastF1 responses. FastF1 returns deeply nested pandas DataFrames that I was serializing into JSON. Writing TypeScript types for these by hand was tedious. Copilot inferred most of them from my Python serializer code and saved me from manually transcribing field names.

🟒 Design system consistency + performance tuning. When I was unifying the visual language across twelve panels (spacing, colors, typography, motion timings), Copilot was great at suggesting consistent token-based patterns and flagging where I'd diverged. It also helped with performance decisions β€” when to memoize, when to use refs over state, when to virtualize, when not to. Not always right, but a useful second opinion.

🟒 Edge case handling. When I was hardening the API endpoints, Copilot was great at suggesting validation cases I hadn't considered. "What if lap_number is negative?" "What if the session hasn't loaded yet?" The kind of paranoid checks that production code needs but you forget when you're prototyping.

🟒 Test stubs. I wrote one test for the gap-calculation logic. Copilot generated the rest of the test cases by varying the inputs. About 70% were useful, 30% were noise β€” but the useful ones caught two real bugs.

Where Copilot was less useful:

πŸ”΄ The creative architecture decisions. The spring-damper camera, the 1000-point SVG sampling trick, the ref-based animation loop bypassing React β€” these required actually thinking about the problem. Copilot suggested generic solutions when I needed weird ones. That's fine. It's a tool, not a teammate.

πŸ”΄ Anything involving FastF1's quirks. FastF1 has a lot of session-specific behavior (sprint weekends, qualifying formats, telemetry availability) that Copilot's training data didn't cover well. It would suggest plausible-looking code that didn't actually work for the data shape.

πŸ”΄ Genuinely novel logic. The first time I wrote the gap-to-track-fraction conversion (offset = gap_seconds / avg_lap_time), Copilot wasn't going to help me derive it. I had to actually understand the math first.

πŸ”΄ Hallucinations when my prompt was vague. This is the honest catch. Whenever I got lazy with my prompting β€” vague intent, no constraints, no examples β€” Copilot confidently hallucinated APIs that didn't exist, function signatures from imaginary library versions, or completely overengineered a solution I didn't ask for. I'd ask for a small utility and get back a 200-line abstraction with three layers of inheritance. The lesson learned the hard way: the quality of Copilot's output is directly tied to how precisely I describe what I want. Vague in, garbage out. It's not the AI's fault β€” it's mine for not being specific.

The honest takeaway:

Copilot is at its best when you know what you want and need to type less to get there. It's at its worst when you don't know what you want and hope the autocomplete will figure it out for you. For finishing up an abandoned project β€” where the hard creative work is already done and what remains is execution polish β€” it's nearly perfect.

It didn't write my project. But it absolutely helped me finish it.

What's Next

The graveyard still has occupants. This is the first exhumation, not the last. I've got a backlog of half-built ideas and I'm coming for every single one of them.

Because it's not about the money. ~ Brad Pitt, F1

Massive shoutout to theOehrly β€” the FastF1 maintainer. This entire project exists because you built something incredible and open-sourced it. That's the energy.

If you're sitting on an abandoned project right now, this is your sign. Open the laptop. Fifteen minutes. The beginning is lying to you.


Built with too many late-night qualifying sessions, more cans of energy drink than I'm willing to admit, and a refusal to add one more tombstone to the GitHub graveyard.

Top comments (0)