The TV runs the game. The phones just hold the buttons.
Playcade puts an arcade on any screen with a browser and turns every phone in the room into its controller. Most of the work went into the parts nobody sees: the network path, the weakest TV in the house, and the browser quirks between them.

Playcade turns the TV into a party game console and everyone's phone into a controller. Open playcade.party on anything with a big screen and a browser: a smart TV, a laptop on HDMI, a streaming stick. It shows a four-letter room code and a QR code. Everyone scans it, picks a name and a colour, and their phone becomes the gamepad. The first phone in holds the remote and picks the game. There are eleven games, from Fuse (lock in as late as you dare) to Turbo (twelve karts on one screen) and Sketchy (draw it on your phone, the room votes on the TV), for two to twelve players. No console, no app, no account.
The TV is the console
The design doc opens with the one decision everything else hangs on: where the game actually runs.
Turn-based games like trivia, voting and drawing only need an action every few seconds, so they run on the server as pure reducers: a phone sends an action over Socket.io and the server sends back a view for each player and one for the TV. Real-time games are different. A racer needs input on the screen in well under 50ms, and a round trip from phone to cloud to TV costs two internet legs.
So for action games the TV is the console. It runs the only simulation and draws the only world. Phones send inputs straight to the TV over a WebRTC DataChannel set to unordered, with no retransmits, so a stale input is dropped instead of blocking a fresh one. The server only helps the two find each other. When WebRTC can't connect, on hotel wifi or a phone on mobile data, the same messages go through the Socket.io relay instead, and the game code never knows which path it's on. There is no TURN server: the relay is the fallback.
Because phones never render the world, there is nothing to predict or reconcile. The architecture doc guards that as a rule: never make a phone render or predict world state.

Built for the weakest screen in the room
The docs assume a 2019 mid-range TV as the baseline, not a dev machine, and that assumption got tested early. A real TV reported 8fps on the lobby while a desktop throttled 6x held 59.5. The expensive effects, glow halos on two dozen critters and drifting background dots, were bound by fill rate, not CPU, so no desktop profile could reproduce them.
The fix was to let the app measure itself. It samples its own frame rate in 2.5-second windows, and after three windows in a row under 32fps it switches to a lighter look for good: same critters, colours and layout, without the costly extras. It never switches back, because a screen that flips between two looks in front of a room is worse than one that stays plain. At 20x CPU throttle with twelve players seated, that took the lobby from 14.6fps to 60.2.
A later performance pass has the most useful line in the repo: trust work, distrust time. Frame rates on a shared machine swing wildly (the same setup measured 18.1 and 5.8fps minutes apart), so the performance gate checks draw calls, overdraw and DOM nodes instead. Baking Flick Carnival's static scenery into sprites took it from 330 draw calls a frame to 72. The pass also records what didn't work: a 30fps render fallback, planned since week one, was built, measured and dropped, because these games are limited by the cost of each frame, not by how many frames they draw.
A television is not a phone
Phones and TVs load the same site, so it has to tell them apart. The first version got a Fire TV Stick wrong: it saw a touch-style pointer and a short screen, decided it was a phone, and asked a television to rotate itself to portrait.
The fix changed what counts as evidence. A device is only treated as a phone with positive proof: a touchscreen and a coarse pointer and a short side, and a browser that says it is not mobile is believed. Anything still ambiguous falls on the side of big screen, because a phone mistaken for a TV can still join by QR, but a TV mistaken for a phone can't start a room at all. There is also a manual override for the TV boxes nobody has tested yet.
Tests that drive the element, not the function
The join screen broke in production twice while every unit test passed. Code that pulled a room code
out of a pasted link had passing tests, but the input box had a four-character limit, and the browser
cuts a paste down to that limit before the code ever sees it. Pasting playcade.party/NHTD gave
the field "PLAY".
The repo's rules now say it plainly: if a behaviour depends on what the browser does to input first (paste, focus, keyboards, the viewport), it gets an end-to-end test in a real browser. New tests are checked by putting the bug back and making sure they fail.
Twelve seats, twelve colours
Every game takes up to twelve players, because a group should never have to shrink to play the next game. Each seat is a colour and a googly-eyed critter, and the twelve colours were tuned until the closest pair was as easy to tell apart as the original eight. That is also why the background is a neutral warm graphite: an earlier plum background had the same hue as two of the player colours, and those two players sank into it.
What's next
The design doc's build order still has audience mode (phones beyond the player limit vote and cheer), a daily race with the same track for everyone that day, and optional profiles. The performance notes keep an open list too, led by an 8-byte binary input frame to replace the JSON packets the busiest games send today.

