Building a Euros sweepstake website with 11ty
We always have a family sweepstake for the Euros and the World Cup so this year I created a website for it: euros.robwood.uk. This is a brief write-up of what I can remember.
The source-code is here.
The basics
I built this website with 11ty and I used a simple starter template I'd created.
The data fetching happens in a global data.js file. When I previously made a World Cup sweepstake site I split the data files up and imported them. That made sense as a way to manage the data but I decided to chuck it all in one file this time. Who doesn't love a bit of chaos?
The API
I used the free football-data.org API to get all the data for this website.
The main problem I had is that I haven't been able to read the API using a token on the client without a CORS error.
This is either something I'm doing wrong or a limit of the free tier. As the documentation shows how make make a request in various programming languages but not JavaScript, I'm assuming it's the latter.
To get around it I make the fetch request during the build process, using 11ty fetch.
As a result, the website would only update when I deployed the site to Netlify. I needed a way to deploy the site daily so the data was at least correct the following day.
Deploying the site daily
Before I decided how I'd do this I needed to set up a Netlify Build Hook first.
I'd previously used the IFTTT service to hook into this Build Hook. Unfortunately, this ability is now part of the 'Pro' tier and is no longer free. I had to look for another way so I decided to give GitHub Actions a go.
I found an article that shows how to trigger a netlify build every day. To create the new workflow in my repo I went to the 'Actions' tab then the 'set up a workflow yourself' link.
The only things I changed in the example code were the build hook URL and the time the workflow is triggered.
This did the job!
Assigning the family members
The API gave me most of what I needed but I wanted to be able to assign a family member to each team when it came to the fixtures, results and standings.
I cloned the teams array and created a new property called 'family_member'. I then assigned each team to a family member. I also created an assignFamilyMember
function that I could use for the fixture, results and standings.
Graphics
I wanted it to look like an old 8-bit football game but that didn't quite pan out. The most authentic typefaces I could find were also pretty that were actually readable so I played it safe with Roboto Mono.
I created pixel-art style icons for family members and the country flags. I based the family member's heads on those in the 90s football game Sensible Soccer.
I'd planned on using some flag icons I found online but in the end I decided to recreate my own 8-bit style versions (inaccurate aspect ratios and all).
The PWA
I don't have a lot of experience with PWAs so I created the minimum needed for a user to be able to add the app icon to their homescreens.
There are two things needed for a PWA (in addition to serving the website over https):
Manifest
This file tells the browser how it should display the app. It includes things like the name, start URL colours and logos. This is in the JSON format and follows a straightforward convention.
Service worker
The service worker file runs in the browser separately to the main app.
It can handle network requests, manage the cache and do all sorts of things I haven't dug into yet.
I ended up using an example service worker from Google to fulfill the requirements of a PWA.
What I ended up with
A website that does the job!
It's far from perfect but it's an improvement on the last sweepstake website I made. I just need to improve it in time for the 2026 World Cup in North America!