xPitch — Strava for Football

OpenAI Build Week submission · Track: Apps for Your Life · Built with Codex + GPT-5.6

Inspiration

I love playing football, but I could never find an app that analyzes my own playing data the way we see professional matches broken down on TV — heatmaps, positional zones, sprint counts, heart-rate load. That data exists: my smartwatch already records GPS and HR every second of a match. It just had nowhere to go.

Strava is amazing for running and cycling, but it treats a football match like a jog around a field. Football isn't a jog — it's stop-start, multi-directional, played in halves, and all about where on the pitch you spend your energy. I wanted the Strava experience, but built around how football actually works. So I built xPitch.

What it does

You upload the .fit file from the smartwatch you wore during a match. From that, plus a little context (your age, the pitch geometry, attacking direction, and how the recording splits into halves/sessions), xPitch turns raw GPS into football insight:

  • Positional heatmap and zone occupancy: where you actually spent your time, mapped onto a real pitch.
  • Movement trail and average position: your shape over the match.
  • Work-rate and intensity metrics: distance covered, sprints, high-speed running, and HR zones.
  • A shareable report card : a letter grade with work-rate / intensity / endurance sub-scores and a role estimate (e.g. "box-to-box engine").
  • Historical Data: now, that we can record our play, we can analyze the historical data. Unfortunatelly, I only play twice since I build this project. So, I don't have enough data. Yet.

Almost everything is automatic. Matches can be saved to the cloud (using supabase), shared via a public link, or exported as an Instagram-ready post/story image generated straight from your data. Because, I want to "impress" my friend :D

How we built it

I started a rough prototype the weekend before I heard about Build Week (a few early commits used another assistant). Once I found the hackathon, I stopped, waited for my API credits, and rebuilt the project around Codex with GPT-5.6 — which is where the vast majority of the real work happened: refactoring the prototype, designing the data pipeline, adding the backend, and hardening the code.

The architecture came together in layers, and Codex drove each one:

  1. Local-first analysis. A dependency-free .fit decoder parses the binary file entirely in the browser — no upload required to get results, which keeps it private and fast.
  2. Insight engine. From the cleaned GPS/HR stream I derive distance, speed zones, sprint/high-speed-running counts, HR zones, fatigue, and a role estimate.
  3. The pitch layer. This is the hard part. Raw lat/long isn't enough for a football heatmap — you need the pitch's real geometry and orientation. I let the user place four corners on a satellite map, and fall back to a PCA-based orientation guess when they don't.
  4. Session splitting. A match isn't one continuous effort like a run, so I built semi-automatic splitting that detects breaks (e.g. half-time) from the HR signal, with manual override.
  5. Cloud + social. I added Supabase for accounts, profiles, saved matches, photos, and sharing — so friends can use it with their own accounts — plus a social-media image generator.

My Codex workflow was a tight plan → build → review → fix loop: I'd describe the feature I wanted, have Codex propose a plan, implement it, then act as its own reviewer before I merged. Codex accelerated the parts I'd normally lose whole evenings to — the FIT binary format, the coordinate transforms, the Supabase schema and row-level security — and let me stay focused on the football logic and product decisions. Later I asked a friend to stress-test it and, with Codex, added automated tests and engineering best practices.

The whole thing is deployed on GitHub Pages. All free. :)

Challenges we ran into

  • The data is deliberately minimal. A watch only gives GPS and HR — no ball, no camera, no vest array. That's a constraint, but I leaned into it as the point: simple in, meaningful out.
  • GPS alone isn't football. To get a realistic positional map I needed the pitch's geometry and attacking direction. The great-circle distance between fixes uses the Haversine formula:

$$ d = 2r \arcsin!\sqrt{\sin^2!\left(\tfrac{\Delta\varphi}{2}\right) + \cos\varphi_1 \cos\varphi_2 \sin^2!\left(\tfrac{\Delta\lambda}{2}\right)} $$

and I project each fix onto pitch-local coordinates using the field corners. My GIS background made this tractable.

  • Orientation without input. When a user skips drawing the pitch, I estimate the playing direction with PCA — the dominant axis of the position cloud is (usually) the length of the pitch, recovered from the covariance matrix:

$$ \Sigma = \frac{1}{n}\sum_{i=1}^{n} (\mathbf{x}_i - \bar{\mathbf{x}})(\mathbf{x}_i - \bar{\mathbf{x}})^\top, \qquad \Sigma\,\mathbf{v} = \lambda\,\mathbf{v} $$

  • Matches have periods; runs don't. I had to build custom, semi-automatic session splitting driven by the HR timeline so "first half vs second half" means something.
  • Handling messy reality — different match formats, orientations, and inconsistent GPS.
  • Getting test data was absurd. My Huawei watch has no football mode. So I set it to running mode, played, synced to Strava, and exported the .fit — just to get realistic data to build on. For other more common swart watch like Garmin, it's much more simpler

Accomplishments that we're proud of

  • The heatmaps and zone-occupancy maps are genuinely beautiful — and they're built from my own matches, not a demo. I impress my friends with it, feel like a real football player :D
  • A dependency-free FIT parser that decodes the raw binary (including compressed timestamps and developer fields) entirely client-side.
  • Football-aware analysis: format-aware thresholds (futsal / 7-a-side / 11-a-side), half-time-aware orientation flipping, and a role estimate that's honest about being an estimate.
  • Privacy by default — the core analysis runs locally; nothing has to leave your browser to see your stats.
  • A complete product loop — from raw file to cloud-saved match to a share link to an Instagram-ready image.
  • Real engineering rigor — refactored architecture and automated tests, developed and reviewed with Codex.
  • It works, and people want it. I have a real tracker for my own football matches with a built-in content generator, and my friends have asked for accounts.

What we learned

  • Football analytics from the inside — what sprints, high-speed running, and work-rate actually measure, and how pros frame them.
  • GPS is only half the story — positional accuracy needs real pitch geometry, not just raw coordinates; that's where GIS thinking mattered most.
  • The .fit format — its binary structure, message types, and quirks.
  • How to build with an AI agent — that a tight plan → build → review → fix loop with Codex lets one person ship something that would normally take a team.
  • End-to-end software engineering — from a local prototype to a deployed, tested, cloud-backed product.

What's next for xPitch

  • Open it up to everyone. Friends have tested it and the feedback is great — next is a public launch where anyone can sign up with their own account.
  • Strava integration — so you never have to export a .fit by hand (pending a Strava subscription for API access).
  • Garmin and other watch integrations for a seamless experience — the format is already compatible.
  • Apple Watch support — the acrobatic one, given its export restrictions.
  • Deeper analytics — per-90 stats for fair comparison, teammate/opponent comparison, and load management over a season.

Built With

Share this project:

Updates