My Fantasy Premier League dashboard.
Topic
Data & APIs
Tags
- Football
- APIs
- AI
Built with
Okay so I need to tell you about football first. Stay with me.
I've been obsessed since the 2002 World Cup. Brazil. Ronaldo, Roberto Carlos, Cafu. And my guy, Ronaldinho.
When he moved to Barcelona, I became a Barça fan for life. And then one day I noticed this small kid on the team called Lionel Messi. You know how that turned out.
I played fantasy football pretty much nonstop from 2004. And I've shown up for every single World Cup. 2014 broke my heart. (Germany 1, Argentina 0. I'm fine. I'm not fine.)
Then in 2018 I moved to Canada. The matches were suddenly on at weird hours, and I kind of drifted. I still showed up for every World Cup from here though. And then 2022 happened that completed football for me (and my G.O.A.T 🐐).
This summer, the World Cup came to North America. Where I live! I played the World Cup fantasy game with my colleagues and had way too much fun. So when the new Premier League season started, I made a team.
If you've never played, Fantasy Premier League is a game where millions of adults pretend to manage footballers and then get genuinely upset about it on a Sunday. Every single week it's the same three questions. Who do I buy? Who do I start? And whose fixtures are about to get ugly?
And like, immediately I'm thinking, there is SO much data here. Every player. Every match. Every price. All of it just sitting there on the official FPL site.
So here's the honest reason this exists. I did not set out to build the best FPL tool on the internet. I wanted to know how you actually get data from somewhere else and do something with it. Like, how does that even work? And could Claude take that data and turn it into something I can look at? FPL was the perfect playground.
Fair warning before we go on. The dashboard is not in great shape right now. It's a sandbox, not a product. So this entry is less "look at my app" and more "look at what I learned poking at it".
It's also the project where I learned that getting data from one website onto another is NOT "just grab it". More on that in a bit. There's a bouncer involved.
What I pointed the data at
Once the data was showing up, I needed something to do with it. So I listed what a manager actually does each week, and each job got its own screen.
Screen | The question it answers | What I tried |
|---|---|---|
Player Explorer | "Who do I buy?" | Compare up to four players. The best number in each row gets highlighted. Except ownership. |
My Team | "Who do I start?" | Build 15 players under £100m. Share the squad as a link, no account. |
Fixtures | "Whose run is about to turn?" | A blank week is NOT an easy week. |
Player page | "Wait, is he even fit?" | Injury news goes first. |
Let me explain a few of those, because even in a sandbox I can't switch the designer off.
Ownership has no winner. Like, think about it. A player nobody owns is a sneaky differential. A player everybody owns is safety. Highlighting either one would be me having an opinion about your team. And you already have a group chat for that.
Blank weeks. Imagine your player has no match this week. Is that an "easy fixture"? No! It's zero points with extra steps. So blanks get counted on their own, and the difficulty score only looks at games that are actually played.
Injury news first. Because "out until March" cancels every number below it.
The share link is my favourite small thing. Fifteen players and a formation fit inside a link. So the link IS the save file. No database, no login. When that clicked for me I was unreasonably happy.
Then the browser said no
Here's where I got humbled. The dashboard is just a folder of files sitting on the internet. There's no server of mine behind it. The data lives on the official FPL site. So my page loads, asks FPL for the player list, and shows it. Easy. Right? RIGHT?
Nope. Nothing.
Turns out browsers have a rule. When a page on one website asks a different website for data, the browser first checks that the second site said "yeah, other sites can read this". The FPL site doesn't say yes. It doesn't say no either. It says nothing. And the browser, like the world's most literal security guard, throws the answer in the bin.
I had to stop here and actually learn what was going on. (The rule has a name, by the way. CORS. You can forget it now.)
The fix is a middleman. One that I control. Imagine a bouncer standing between my dashboard and FPL. My dashboard asks the bouncer, the bouncer asks FPL, and hands the answer back with a little permission slip stapled on. The browser sees the slip and goes "oh okay, carry on".
That bouncer is a tiny bit of code running on Cloudflare (they call it a Worker). And it's strict. There's a guest list of exactly six things it will fetch. Anything else gets a polite "not found", plus the list of what IS allowed. Basically "nice try".
What the dashboard asks for | Does the bouncer keep a copy? |
|---|---|
Every player, team and gameweek | Yes, for 5 minutes |
All the fixtures | Yes, for 5 minutes |
One player's history | No |
A manager's name | No |
A manager's season so far | No |
A manager's squad for one week | No |
Why keep a copy at all? Because that first one is ENORMOUS, everybody needs it, and it barely changes minute to minute. Asking FPL for it fresh on every single visit would be slow and kind of rude. So the bouncer holds on to it for five minutes and hands that out.
And putting the bouncer live on the internet? One line. I'm not joking.
One line, and it's live worldwide. It felt illegal.
Things the data taught me (the hard way)
The data had opinions too.
Every club has two different ID numbers. For 19 of the 20 clubs, they don't match. Manchester City is 15 in one and 43 in the other. Badges, shirts and photos all use the second one. Mix them up and you get the right player in someone else's kit.
Player photos don't exist at every size. About one in six of the top scorers just isn't there at the bigger size. So the app quietly checks first, and shows the club shirt when there's no photo.
And in pre-season, looking up any manager's team came back "not found". For every manager on earth. Because nobody had picked a team yet. Everyone's form was 0.0. That's real data, not a bug. Still felt personal.
For the stack people.
Part | What I used |
|---|---|
The app | React, built with Vite |
Hosting | GitHub Pages |
Data | The bouncer (a Cloudflare Worker) in front of the official FPL data |
Saving your squad | Your own browser, plus a share link |
I started this on July 24, and like I said, it's rough. The Wildcard and Free Hit chips only started working at the end of September, weeks into the season. That tells you everything about how my roadmap works. I start one thing, something else bugs me, and I follow it.
But a polished dashboard was never really the point. The point was learning how data gets from over there to over here, and what Claude can do with it once it arrives. That part? That part worked.
If I keep going, next I want league tables from outside the Premier League. That needs a second bouncer and some secret keys I have to keep hidden. I've never done that before. I'll figure it out as I go.
Keep reading


