Chris's Questions: Three Live-Multiplayer Games on One Server

Three party games — Second Guess, Dial It In, and Dial It In · party — that share one Node.js server, one deploy target, and one brand-switch layer. Each game solves a different real constraint: no survey data available, livestream lag makes speed meaningless, and no host or shared screen in the room. Live at questions.chrisabass.com.
🎮 What it is

Three real-time multiplayer party games, one shared server, one URL

🧱 Stack

Node.js standard library only — no npm install, no build step, no dependencies

☁️ Deploy

Google Cloud Run container, custom subdomain, in production today

🕰️ Origin

Started as a corporate Family-Feud tournament for a 20-team Employee Appreciation Week; generalized into a public tri-game platform

Second Guess — the AI-authored answer key

For a room with one shared screen. Everybody answers the same question at once from their phone, and you score what the answer was worth.

The constraint

Survey-based game shows work because a production company paid a research firm to ask 100 people what they think about something. That answer sheet is the game. Without it, there's no game — you can't judge whose answer was "worth more" if nobody agreed on what the right answers were.

Independent developers don't have a research budget. So a public version of the genre needs a different way to get an answer key.

The design answer

An AI writes the answer key. Every Second Guess question ships with a set of accepted answers and a weighted score for each one, all authored ahead of time by Claude — not scraped from a real survey, but built to look and feel like one. The game runs against that answer sheet, not against live players' votes.

This inverts the usual mechanic. Instead of asking "what did the crowd say?" the game asks "what did the AI think the popular answers would be?" — and the players are guessing what the AI guessed.

What that made possible

  • Every player answers at once, from their own phone. No buzzer, no team turns, no waiting. The bottleneck of a physical buzz-in disappears once scoring is deterministic against a fixed answer sheet.
  • The board is a shared screen with the question and a set of hidden answer slots. Answers only fill in as the host reveals them — the board's HTML never contains an unrevealed answer, so nothing can leak through Ctrl+U, screen-share resizing, or a resend of a state payload.
  • Ambiguous responses route to the host for review before scoring, so a fuzzy match doesn't quietly award or reject points behind the game.
  • The whole system works with no phones at all as a fallback — the host types responses on the board's behalf. Same game, same scoring, same answer key.
Second Guess board mid-round: slots 1 and 4 are hidden — only their point values (30 and 21) are shown; slots 2 and 3 are revealed with player names (Ray, Mary). A 15-player scoreboard sits below the board.
The board mid-round. Slots 1 and 4 are still hidden — the HTML for those rows doesn't contain an answer yet, so view-source can't leak them. The scoreboard below is the whole room, answering at once, from their phones.
Second Guess host view of the same question, showing the answer sheet alongside a note that reads "Put the board on the shared screen or in the stream. Nobody joins this room — the answers come through you."
The host's-eye view of the same question. Nobody joins the host's room — the host runs the reveal and everyone else watches the board.
Players list showing 15 named players with live scores, and a disclosure line reading "Answers and points written by Claude, an AI made by Anthropic. Nobody was surveyed. This site is not affiliated with Anthropic."
The app itself tells the room what it is. AI wrote the answer key — no survey, no research budget, no pretending otherwise.

Dial It In — the game that works on a livestream

For any size crowd, including a stream. One clue, one hidden spot on the meter, and everybody guessing at once from their phone. Works with four people or four thousand.

A livestream audience is watching the video 5 to 30 seconds behind whatever the host is doing. Any game mechanic that rewards being fast stops being a game and starts being an internet-latency test — the person on fiber wins, the person on cellular loses. So nothing in Dial It In is scored on speed. Scoring depends only on how close a guess lands to a hidden spot on a meter — a value between two opposites (overrated ↔ underrated, mild ↔ spicy, useful ↔ useless). The band is chosen by the host, players guess after seeing the clue, and the score is the distance. That's the whole rule.

Three deliberate architectural choices fall out of that:

  • Polling, not push. The transport is long-polling instead of Server-Sent Events. It survives Cloud Run idle disconnects, corporate-proxy buffering, and wifi-to-cellular handoffs — none of which are edge cases for a live audience.
  • Guesses are write-only from the crowd. The viewer's phone is the input device and the video is the only output. There's no client that has to render live state fast enough to match the host — because there's no state a player needs to see faster than everyone else.
  • The crowd's mean scores as its own player. An arbitrarily large audience is one entrant on the board, sitting alongside up to a handful of named players. That's how "four thousand people" and "four people at the kitchen table" become the same game.
Dial It In reveal: "The crowd said 73 · answer was 88 · 2 points" above a horizontal Boring-to-Exciting meter with a green marker on the crowd's guess and a yellow marker on the correct answer.
The reveal. Distance between the yellow band (the answer) and the green marker (the crowd's guess) is the entire score. No speed, no buzz-in — that's why a livestream audience running 30 seconds behind can still play.

Dial It In · party — the game with no host

For two to eight people in a room. One phone each, no host and no screen needed. It hands the clue around by itself and stops once everybody has had a turn.

Party games at the kitchen table normally need somebody running the room — reading the card out loud, deciding whose turn it is, tallying points. Somebody has to sit out to run the game. The design goal here was: nobody sits out.

The answer is self-orchestrating turn rotation. There's no board, no host role, no timer server-side. Each player joins from their phone; the game hands the clue-writing seat around the group in order; when everyone has written one clue, the round ends on its own. All state advances via poll timestamps evaluated on request — no wall-clock timers, no host input required. Same mechanic as broadcast Dial It In, same server, same answer-isolation architecture. Just a completely different physical setup around it.

Phone view with a join code EHZP, the clue "teenager" on an Old-to-New meter, and copy reading "You wrote this one, so you sit it out."
Party mode on a phone. The game tells the clue-writer to sit this round out — no host asked, the round just knew whose turn was up.

What the three games share

All three games run out of one Node.js process, one deploy container, and one URL. Under that surface are a handful of design decisions the whole platform inherits.

Answer isolation as an architectural rule

Any screen that gets shared to the room (the game board, the group's shared display) receives payloads that literally do not contain unrevealed answers. What isn't in the payload can't leak — no client-side "hide until reveal" that a curious user could bypass.

Multi-room by default

One deploy hosts up to 20 concurrent games at once, each in its own room, each with its own PIN-gated join door.

Two-PIN system with hot rotation

Host PIN and editor PIN are separate credentials with separate endpoint allowlists. A small CLI rotates either one at runtime without restarting the server — a restart would clear every room's live game, which is why rotation had to be live.

Env-var-driven rebrand

Same static HTML ships regardless of which product name is on the container. Product name, wordmark stacking, and company-logo visibility come from environment variables via /api/config and apply to the DOM at load time. One repo, two live deployments — the private corporate Family-Feud–style tournament this started as, and the public tri-game platform — with no branch or build-time swap. If /api/config ever doesn't answer, the page keeps its shipped copy: safe to fail on a projector at a live event.

Zero-dependency runtime

No npm install, no build step, no bundler. Node.js standard library only. Drops onto any Bitnami/Ubuntu box, ships in any minimal container.

Copyright-safe by construction

Only owned or CC0/OFL assets in the public build — Kenney SFX, Anton and Bebas Neue for wordmarks, no show-branded material. Provenance is documented in the audio credits file, not just implied.

Play it

Pick a room, grab your phone, no install.

Play now →

Want the build story or the source structure? Get in touch.