I occasionally post silly web projects here. Expect things to break often.

Online UNO

An online multiplayer version of the popular card game that runs in your browser. Built for fast-paced gameplay with friends.

Screenshot of online UNO

This web app uses Google Firebase's Firestore database to store game information, and uses the onSnapshot() listener to update each client in realtime. Firestore is generally my database of choice for small/quick projects since it charges per query rather than for an active instance - keeping costs low. There is currently a server API which is used to make plays, but in the future this could be swapped out for an entirely Firestore-native app thanks to the Firestore Rules system.

Domyes 🍕 Tracker

A Domino's pizza tracker reliably tracks your pizza. Designed for the UK Domino's so if you're elsewhere it's unlikely to work.

Screenshot of Domyes Tracker

I put this together because the official tracker has been a bit broken for a few months now, and there's no point in having a pizza tracker if it can't track pizza.

Screenshot of Domyes Tracker

The track button no longer shows up, and you have to refresh the tracker periodically to update it.

How it works

The official tracker uses two domains to get it's data: for order status (e.g. baking, quality control etc.) and for store and driver location. We can't fetch them from our page because they'll be blocked by the browser's CORS policy.

Instead we serve the tracker data from our own subdomains and

To do this, I modified and deployed this script to Cloudflare Workers which acts as a simple proxy server, and adds an Access-Control-Allow-Origin header to the response. This script is handy because we can deploy it to both our new subdomains while maintaining only one codebase.

addEventListener('fetch', event => {
async function handleRequest(request) {
    let url = new URL(request.url);
    // Check if incoming hostname is
    // a key in the ORIGINS object
    let target = ORIGINS[url.hostname];
    // If it is, proxy request to that third party origin
    if (target) {
        url.hostname = target;
        let response = await fetch(url, request);
        response = new Response(response.body, response);
        // Add our origin to the response headers
        response.headers.set('Access-Control-Allow-Origin', '');
        return response;
    // Otherwise, process request as normal
    return fetch(request);

 * An object with different urls to fetch
 * @param {Object} ORIGINS
const ORIGINS = {
    '': '',
    '': ''

We can then replace the Domino's domains with ours and parse the response like normal.