Case study · JS · Canvas · Firebase
The Chicken Office
A 2D multiplayer co-op browser game. Every friend joins the same room as a different chicken type, and the team has to feed and cheer each other through an 8-hour real-time office shift — nobody makes it to clock-out alone.
The idea
Some of my closest friends work long office shifts together and I can't be there with them. So I built the next best thing: an office you survive as a team, where the whole point is looking out for each other. It started as a personal learning project — an excuse to really get my hands dirty with Canvas and real-time sync — and turned into something they actually play.
How it plays
- One key does everything. Walk up to a coworker, a desk or the wardrobe and a hint tells you what E will do right now.
- Help each other. Feeding or cheering a coworker gives +20 health, or +40 to revive someone who has passed out.
- Work a desk. Hold E for about 4 seconds for +15 health. Each desk then needs to recharge.
- Brain breaks. A quick logic question appears 5 minutes into the shift, then every 20 minutes — answer within 60 seconds for +10 health. All 24 questions are scheduled off the room's shared clock, so every room gets the same question at the same minute.
- Passing out. Health at 0 means you're down, and the team has 15 minutes to get you back up before you're out for the shift.
- Extras. Emoji reactions float as speech bubbles, there's a room chat with shared history, and a wardrobe of cosmetic outfits.
Chicken types
Each room allows one player per type, so the team naturally ends up mixed.
🐔 Turbo
Runs much faster around the office — but health drops sooner.
🐔 Zen
Health drains much more slowly. Cool under pressure.
🐔 Tank
Can go a long time without help, at the cost of moving slowly.
🐔 Social
Bigger range to help coworkers, and heals a little while helping.
Under the hood
- No framework. Plain HTML, CSS and JavaScript, split into small files — constants, utils, render, game state.
- HTML5 Canvas draws the office floor, the desks, the boss chicken and every player each frame.
- Firebase Realtime Database syncs players, chat and the shift clock across browsers, with anonymous sign-in so there's no login screen.
- Forward-compatible saves. Every player is just a JSON object; a
migratePlayer()step fills in missing fields with defaults as records load, so adding a new stat never breaks older saves. - Safe rendering. Player names go into the roster through
textContent, neverinnerHTML, and the database rules require auth and validate record shape.
What I took away from it
This was my first time syncing real-time state between strangers' browsers, and the lessons stuck: keep the shared clock as the single source of truth, give every new field a default, and assume any text a player types is hostile until proven otherwise. It also reminded me why I started coding — making something that makes people feel a little less far apart.
← Back to projects