Making a Eurovision Party voting app in 5 hours
Last weekend was the final of the Eurovision Song Contest. Eurovision is a cross-Europe (and beyond) singing competition in which each country nominates a singing act and they compete to find the continent's favourite. It's known for its fun factor, with countries often choosing visually impressive or otherwise unusual acts rather than their best singers.
The final event of Eurovision features the 26 winners of the semi-finals performing sequentially, followed by a public vote. The night finishes with each country revealing its citizens' scores along with a panel of professional judges from the nation. With political voting and bad international link-ups, this is a great part of the night.
For the past few years I've been to or hosted some sort of Eurovision party on the night, where everyone watches along, argues about their favourite acts, munches food and, lately, participates in some sort of Eurovision bingo.
Last year, a friend suggested building an app so everyone at the party could vote along on the night, with a screen in the room keeping track of the total score. It was too late notice at the time but this year, less than six hours before the broadcast started, I decided I could produce something quick enough.
I was also spurred on by recently playing a lot of Jackbox Games products, which involve players in the room using their smartphone to play along with instructions on screen. I've been meaning to try creating a similar game myself, and this seemed like a good stepping stone.
Feature set
The feature set of the app is pretty straightforward. When users open the website for the first time, they are asked for their name. They're then given a list of the evening's competitors and can select a score between 1 and 10 for each.
Once all the songs have been performed, players can switch across to the "Points" page and allocate points to their favourite songs, as if they're an entire European country to themselves. Like the real voting countries, players can select to give 12 points to their favourite song, 10 points to their second favourite, and then 8 through 1 points to the remaining 8 songs they enjoyed.
When players have finished allocating their points, they hit a big "Save judgement" button at the bottom of the screen to send their selections to my server. At the end of the voting period, I then run a script on the server to pull out our final votes.
Building an app in five hours
When I introduced the app, people were impressed that I made it in only about five hours. I was surprised at the result, and repeatedly thought I wouldn't make the deadline. I did also have to miss the Spanish entry to fix a couple of bugs, but they came dead last so it seems I didn't miss much.
I credit the turnaround time mostly to simplicity. There's a lot of talk in the front-end development community about how involved starting a new project is: selecting a JavaScript framework, selecting what language to actually write in and transpile from, finding all the tools to hook the two up, and then installing everything through your package manager of choice.
Instead of going through that whole process, I just decided to use plain HTML, CSS and JavaScript. No frameworks, no dependencies. Everything was going to be client-side rendered, whilst using JSON files and localStorage instead of databases.
Admittedly I had some unusual benefits here:
- I didn't have to worry about scalability beyond 20 people
- All the players had a fairly recent smartphone with a fairly modern web browser
Frankly though, the second point is extremely often true of the target audience of new apps, and the scalability could easily have been handled with some minification-at-deployment and use of Service Worker.
I made a few other simplifying architectural decisions. I used John Resig's extremely simple micro-templating function for all templating. This function is quite limited in functionality (and safety) but was perfectly suitable for my use-case. I also decided to use the Fetch API, which is possibly my favourite web platform feature of the past couple of years. I included the GitHub fetch polyfill in case anyone present didn't have quite the most modern of browsers and because it was easy.
Using these modern web platform features made development extremely easy. In moments I had client-side rendering templates based on a pre-prepared JSON file, with interactive elements that stored data in the client so would persist on refresh.
And, because I was storing the data on the client, the impact on my server was completely minimal. A few hits on initial page load, but no navigation and no need to refresh.
Later in the afternoon I added the server-saving element, which was a single Node script hosted by nginx which would partially validate the submitted data and store it as a JSON file using the submitter's username. I used Express to simplify routing and cors, but the rest was pure Node.js JavaScript.
What was missing
There was one key feature I overlooked that pretty much everyone who played along pointed out to me: in contravention of Eurovision rules, everyone could vote for their own country. The UK, who were grossly over-represented at our party, didn't seem to benefit from that at all though.
There were some technical bits I would have liked to tidy up. Firstly, introducing Service Worker would have made this much more compelling. For those who closed their browsers or tab, they would be able to re-open the app instantly with no data usage. It could even have saved to home screen, which I think would've made people feel more comfortable thinking of it as an "app" (though in the end no-one brought this up).
I also should have added more validation to the server-side. If anyone had wanted to, they could have submitted any number of points to any number of competitors. Again though, this wasn't really an issue because the only users were a room of 20 or so friends who had no interest in breaking it.
What's next?
I'd like to do some work on the app and bring it back next year. The improvements above would certainly be added. I'd like to make it possible for multiple parties to compete, so they can each set up their own "room" that guests can join. Then we can, for example, see which party is closest to the final results. I also like the idea of everyone who joins being assigned a competing country, to closer simulate the actual voting process and introduce a bit of additional competition.
The most significant piece of work would be to build up more on the admin side. This year, JSON files were uploaded to my server and I wrote a script to crunch them and calculate final scores and averages. That process should be automated, update in real-time and show the room how their votes are going.
Lessons learnt
Mostly, the experience of building, releasing and using this app so quickly was hugely inspiring. Whilst side-projects have previously involved lots of build-up, long schedules and consideration of scalability, I'm now inspired to work much more quickly to create prototypes that _just work_, without complex libraries and brazen attempts to look professional.
I don't think my upcoming projects are likely to be quite so simple as to just use micro-templating, but I'd love to find a templating engine which allows similarly negligible turnaround time and file size whilst being slightly more robust. I'd also love to not use package managers again.
The feedback I got from the app was really positive, which was similarly inspiring. Next time I've got an idea, and a few hours spare, I'll definitely try to build it.
You can still see the app in action (though saving judgements has been turned off) and find the source code on GitHub.
🎶🎧 Writing music for this post: Admiral Fallow – Tree Bursts in Snow