Project

Uppy

A silly co-op multiplayer browser game built entirely on the Cloudflare edge stack. Tap to keep the balloon airborne; the more players in your lobby, the harder it gets — and the higher you can score together.

Type
Multiplayer Game
Status
Ongoing
Year
  • Cloudflare Workers
  • Durable Objects
  • D1
  • Multiplayer
  • TypeScript

Uppy is a co-op multiplayer browser game where a balloon is in the air, a bird tries to pop it, and the only way to keep the balloon up is to tap together. Each player has a short cooldown between taps, so coordination matters more than reflexes. The more people in your lobby, the harder it gets — and the higher your collective score can climb.

It's free, works on phones, and takes about ten seconds to join a game.

The Stack

The whole game runs on Cloudflare's edge platform. No traditional servers anywhere.

  • Cloudflare Workers — single binary backend, no infrastructure to manage
  • Durable Objects — per-lobby state. Each game room is its own DO with consistent state across every connected player, WebSocket fan-out built in
  • D1 — cross-request persistence for auth, profiles, and scores
  • Cloudflare Email Service — magic-link login emails
  • Cloudflare Access — gates the dev environment
  • R2 + Assets binding — static asset hosting from the same Worker
  • PostHog — analytics and in-game feedback surveys
  • Plain JavaScript on the client — no framework, no build step, single module

The whole thing deploys with wrangler deploy. Total infrastructure cost so far: free tier.

Why this stack

I wanted to learn Cloudflare's edge platform properly, and a real-time multiplayer game is one of the harder things you can build on it — if it works for a game with sub-100ms per-tick state sync across continents, it'll work for almost anything else. The constraints turned out to be the right ones: forcing every piece of state to live in either a Durable Object or D1 made the architecture obvious in a way that "stand up a server and put Redis next to it" doesn't.

What I learned

  • Durable Objects are perfect for multiplayer state. Real-time sync across clients without needing Redis or Pub/Sub — the DO is the source of truth and WebSocket fan-out is built in. No glue code, no separate state service.
  • The state management is the hard part. Not the WebSockets, not the rendering — the cooldown logic, the score reconciliation, the rejoin-after-disconnect edge cases. The kind of work that doesn't show up in a tutorial but eats your weekend.
  • Playtesting with strangers is a different beast. Real human latency, real weird inputs, real "I clicked, nothing happened for 2 seconds, then 5 things happened" reports. Logs you can't reproduce in dev.
  • The free tier goes further than you'd expect. A single Worker, a handful of Durable Objects, a D1 database, and the Email Service — none of it costs anything yet at the volume Uppy runs at.

Play it

uppygame.com — free, no passwords, drop your email once for a magic-link sign-in and you're in. Mobile-friendly. There's an in-game feedback prompt after each round; that's the fastest way to tell me what's broken or what would make it better.

More projects

Pixelated Realms Podcast

Pixelated Realms is your guide through the digital landscape, untangling the mysteries of your favorite titles and discussing the latest and greatest in video game fun!

Read more

Raid

An open-source command-line tool that orchestrates distributed application development — managing repositories, environments, dependencies, and testing across multi-repo codebases from a single configurable YAML system.

Read more