Building a TV game show for a house party
Three teams, a big screen and everyone's phone as a buzzer. Notes from building Le Grand Quiz d'Yport, and what turned out to be hard.
- teams
- 3
- editions
- 2
- code
- ~12k lines
- tests
- 70-odd

The brief was one sentence: a proper game show for an evening with friends in Yport, on the Normandy coast.
Not a pub quiz. Not questions read off a sheet with someone keeping score on a napkin. I wanted the thing you see on television: a big screen, a host with a console, teams that buzz in, jingles, a podium at the end. And, because a real show has them, ad breaks.
I could picture the tempo exactly. Round card. Question. Music tightening. A buzz cutting the music dead. Silence. Reveal. That mental clip turned out to be the most valuable asset in the whole project, and almost every wrong turn later happened because a detail had drifted away from it.
What I couldn’t picture was which parts would be hard. I assumed the difficulty would be technical: phones on flaky Wi-Fi, buzzer timing, video playback. Those took an afternoon. The hard parts were writing questions that are fun to get wrong, and building a console that one slightly tipsy human can drive for ninety minutes without losing the room.
The setup is one laptop doing three jobs: the presenter’s view on its main screen, the game on the television as an extended display, and a local server that the phones join over the same network. Each phone becomes a remote control for buzzing, answering and voting.
Scroll across to follow the connections →
A show, not a quiz
I kept coming back to one question: how do you keep a room on its toes for more than an hour?
Two decisions shaped the evening. Keep each round short, four or five questions. And mix the ways people answer, so that just as the room settles into a rhythm, it gets a different reason to pay attention.
01 / Keep rounds short4–5 questions.
Then change the rhythm.
02 / Mix the mechanicsListen, choose,
estimate, remember.
There’s also a mischievous variation: the lying round, borrowed from Fibbage. Each team invents a fake answer, the fakes are mixed with the truth, and everyone votes. Points for finding the truth, points for fooling your friends.

Those two layers, how you answer and what the question contains, stay independent. Any clue works with any mechanic. That is what lets a round keep changing without asking the room to learn a new game.
Between rounds, the ad break. A television-style bumper, bars sweeping across the screen in the team colours, then a short fake commercial, thirty seconds of nothing at stake. It was meant as a joke. It became the moment people refilled their glasses, argued about the last answer, and came back ready. Every show has a break for a reason.
The spec did most of the work
Before any code, I wrote a two-page requirements file. Not a formal document, just the evening in plain language. It’s still in the repo and I still open it.
Two lines at the top outranked everything else:
- Reliable on the night. Simple, tested game logic, and a host who can fix anything by hand.
- Staging that lands. Rhythm, sound and transitions make the evening. Staging is a separate layer that reacts to game events, never mixed into the logic.
Then the table of mechanics, the table of content types, and the one sentence that quietly decided the architecture: any mechanic works with any content type.
Writing it down first meant I never had to argue with myself about scope. Every time I wanted to add something on a Sunday afternoon, I checked it against the file and usually the answer was already there.
I built it with Claude Code, working as a pair. The division of labour that worked, and that I’d keep: I own taste, tempo and truth (the content, the rules, what the audience sees). It owns the state machine. I never opened a socket handler. I spent my time on the parts a machine can’t have an opinion about: whether a question is funny, whether a round drags, whether the joke on screen lands at the right second.
Making it look like television
A game show is recognisable before a single question is asked. The colours, the type, the way the lights come down for a reveal. So before building screens, I watched shows and played games with a notebook open.
Who Wants to Be a Millionaire taught the reveal. Everything darkens, the four answers sit in their lozenges, one of them starts to pulse, and the delay before the colour changes is the whole show. The screen itself does almost nothing. The music and the wait do the work.
The same idea in my game, in three beats: the question, the team that gets the floor, the answer.
The player’s side of the show
The Jackbox games taught the phones. A phone is not a second screen, it’s a hand: it shows only what you need to decide, right now, in big letters, and nothing you could cheat with. Jackbox also proved that people will happily draw, type and lie on a five-inch screen if the TV rewards them for it two seconds later.

In practice, one phone belongs to the whole team. The team picks its colour, counts its players and frames their portraits. Once the game starts, that same browser tab becomes a buzzer or an answer pad. The question stays with the host or on the big screen. The phone only ever shows the next action.
[French TV game shows] taught the host. The host is on camera even when nothing is happening, and the console has to let them fill that time with something better than “hang on, let me find it”.
Then I iterated the look in Claude Design: the round card, the reveal, the standings, the ad bumper, the lobby. Rounds of sketches, each one thrown on the actual television to see what survived at three metres in a dark room. Most things didn’t. Text got bigger, palettes got shorter, everything that moved got slower. The version I kept has [a small number] of colours, one display typeface, and one rule: whatever is on screen should be readable by the person furthest from it, holding a drink.
Three rules that held everything together
Almost all the stability came from three decisions made on day one.
The server is the only source of truth. Every command goes through one pure function:
reduce(def, state, cmd, actor, ctx)
No side effects, no clock reads, no randomness except what’s passed in. If a command is refused, the state is unchanged. The state is written to disk after every command, so restarting the server mid-game picks up exactly where it was. I restarted it during the real party. Nobody noticed.
Views contain no rules. The server sends each client the complete view for its role
(PublicView, PlayView, HostView) and nothing more. The phones do not have the answer in
memory. A phone that reconnects is instantly correct because there’s no local state to resync.
During a lying round, the other teams’ lies aren’t on your device until they’re meant to be.
Staging is a separate layer. The engine emits events (buzz.locked, answers.revealed,
score.changed) and a single cue file translates them into sounds, music and effects. Changing
the tempo of the whole show means editing one file. Nothing in that file can break the game.
Those three rules are why the codebase stayed around twelve thousand lines and still reads cleanly after two editions.
A lesson from the build
The host console is the actual product
The public screen is what people remember. The console is what makes or breaks the evening, because the host is holding the room’s attention while operating the whole thing.
I knew I needed to stay in control. Speed up if a section was getting boring. Go back if a contestant felt frustrated by how something played out. Replay a moment simply because it was funny. Those are decisions you make by watching people, and the console had to make them easy to act on.
Borrowing the cue list
I remembered how live shows and theatres run cues: prepare the sequence in advance, then trigger each moment when the room is ready. I briefly looked at cue software, including QLab, where a GO button advances the prepared cues. That was the interaction I wanted to borrow.
In my game, a cue might start a sound, move to the next question or reveal an answer. The result is a hybrid: a prepared running order, with manual controls always within reach.
In the normal flow, I mostly press the spacebar. Depending on the question, the sequence takes me through introducing it, reading it aloud, taking answers or buzzes, validating a response, and revealing the solution. The main action stays in the same place. A standby line tells me what the next press will do, and what comes after it. When a buzz needs judging, Accept / Reject take that spot. I can keep talking without hunting through menus.

01 / TOPOne action to keep moving.The spacebar action and standby line sit together, above the rest.
02 / RIGHTRoom for mistakes.Each team has its own score corrections and a way to answer on its behalf.
03 / BOTTOMA way out of the noise.Sound cues and Stop all stay within reach.
Keeping an eye on the room
The running order gives me a default rhythm. The live view tells me when to change it.
- Give a discussion room to finish. I can see the time left and add fifteen seconds if teams are still debating. If the energy has dropped, I can close the answers and move on.
- Watch the hesitation. Live responses show who has answered, who is still thinking and who changes their mind. That gives me something to comment on or joke about while we wait.
- Fix things in front of me. Grant or remove points, undo a correction, answer for a team whose phone died, or reopen the buzzer for a specific team. Going back or replaying a section is part of hosting, so those controls belong in the console.
- Get people back into the game. I can bring the QR code back onto the big screen when someone leaves the page. This happened a couple of times; reconnecting had to be easy.
- Play to the moment. Applause after a joke, a jingle, a little tension music while someone hesitates. I can trigger sounds independently of the running order. Escape is STOP ALL: it cuts media, music and effects without changing the game state.
Something to say after the reveal
I also added a few fun facts and extra explanations to each question, visible only to the host. After the answer, I have a “did you know?” ready for the microphone. It gives the reveal a little afterlife: something to laugh about or discuss before moving on.
Those notes live alongside the question and the live responses. In the capture below, one team has answered, two are still thinking, the clock is nearly out, and the extra facts are already there for me to use after the reveal.

Separating those facts taught me something too. Early on I’d been writing notes to myself inside explain,
the field that gets displayed on the television. My stage directions were one reveal away from
being projected to the room. Now there are three fields for three audiences: notes for the
host’s instructions, facts for the microphone, explain for the screen, and the code enforces
where each one can appear.
Writing the questions was the hard part
I expected content to be the easy half. It’s the half I’m still doing. The engine makes the show run on time. The questions are the show.
A good party question is one where being wrong is fun. “Who directed Titanic” is a fact check: either you know it or you sit quietly. “How long did the Titanic take to sink” is an argument. Everyone has a number, everyone’s number is wrong, and the reveal is a small event. I cut several correct-but-inert questions late, the director one included, because they produced silence.
Two options is not a question. I had written “Was Cleopatra Egyptian? Yes / No”. A coin flip, and the interesting fact (she was Greek, from the Ptolemaic line) arrives as a technicality. Rewritten as “Where was Cleopatra from?” with four options, the same fact becomes a surprise and the teams have to commit.
The fake answer needs a real-sounding neighbour. “Which of these straits doesn’t exist?” only works if one of the real ones sounds made up. Nobody suspects Hormuz or Bering. Everyone suspects Lombok, which is real. The invented one hides behind it.
Same answer twice kills the second question. In the cover-version round, I had two songs whose original singer was Claude François. After the first, the whole room typed “François” on reflex. One got cut.
Break the pattern before it becomes one. After three “the French version is actually a cover” questions, teams assume every song is a cover. So the fourth one is an original. The people who’ve stopped listening lose.
Mechanics belong to questions, not to rounds. I’d modelled a round as “a mechanic plus a list of questions”. Then I wrote real content and immediately wanted a buzzer, a multiple choice and a number guess inside the same category. The content forced an engine change: each question now carries its own mechanic and scoring, and a round’s default only applies to the questions that use it.
Questions read aloud need to be hidden. readAloud: true keeps the text off the TV and the
phones while answers are open. Otherwise the fastest reader wins, which is a different game and a
worse one. A read-aloud question opens the buzzers the instant it appears, so the host can be cut
off mid-sentence by someone who already knows. That interruption is one of the best sounds of the
evening.
Generate what you can’t find. Some rounds needed audio that doesn’t exist: an electro version of a scout hymn, a French YMCA. I made them with Suno, asked for a long instrumental intro, and cut the clip right before the recognisable part. Bonus points if you get it from the intro.
Cut into a drawer, not a bin. Preparing the second edition I cut five categories to keep the
evening under time. They live in reserve-categories.yaml, which is itself a valid game. Nothing
lost, nothing cluttering the running order.
Testing a party that hasn’t happened yet
You get one take. There’s no staging environment for a living room. So a verification loop ran before every commit:
npm run checkvalidates the content file and confirms every media file it references exists on disk.- Seventy-odd tests against the pure engine, including a full end-to-end game.
npm run simulateruns three simulated phones and a simulated host through an entire game over the real protocol.- For anything visual: build, throwaway server, and a look at the actual pixels on the actual television.
The last one is the one that matters. Everything that ever looked wrong looked fine in a browser window and wrong on a 55-inch screen in the dark.
The checklist for the night lives in the README and is mostly not about code: plug the laptop in, disable sleep, let Node through the firewall, click once on the public screen so the browser is allowed to make sound, and have the phone hotspot ready for when the house Wi-Fi gives up.
Two extras that made it a show
Players in the show. Each phone asks how many players are on the team, and each player takes a selfie and frames their face in an oval. From then on, little characters in the team colours, wearing the players’ real faces, dance in the lobby, jump when it’s their turn, celebrate or sulk at the standings, and run toward the category their team voted for. Rendering sits in one component with a pose prop, so a 3D version can replace it later without touching anything else.

Teams choose what’s next. Borrowed from Knowledge is Power: between rounds the screen offers up to four remaining themes, each team votes on its phone, and their characters run to the tile they picked. Ties go to the team currently losing. I assumed this would mean some categories never got played. It doesn’t: every round still gets played, and the vote only decides the order. Real influence on the shape of the evening, no content wasted.
The day after
Everything worked. Keeping the system simple paid off: every phone connected on the first attempt, and the ones that dropped rejoined quickly. I could manage the pace, reopen a question when needed and keep the game moving. It was as much fun to host as to play.
The small things mattered too. Seeing their own faces on the characters and choosing the next category gave teams reasons to stay involved between questions. Two days later, we played again with a new set of questions. Not bad for something built for one evening.
Writing the next edition
Each played edition is archived in editions/, with its saved state and photos, while
game.yaml holds the next one. Preparing another game mostly means writing new material, in
categories like this one. The category sets the
defaults: multiple choice (qcm), twenty seconds, and a place in the vote for the next theme.
Each question can override the mechanic. Here, a number guess and a read-aloud buzzer question
sit between two multiple-choice questions.
- title: "Science"
mechanic: qcm
vote: true
icon: "🔬"
time: 20
questions:
- text: "What is the chemical symbol for gold?"
choices: ["Ag", "Au", "Or", "Go"]
answer: B
explain: >-
Au, from the Latin aurum.
Ag is silver, from argentum.
facts:
- >-
All the gold ever mined would fit in a cube
roughly 22 metres on each side.
- >-
A single gram of gold can be drawn into a wire
more than two kilometres long.
- text: "How many bones are in an adult skeleton?"
mechanic: number
answer: 206
unit: bones
explain: >-
206 bones. A baby has nearly 300:
many fuse together as they grow.
facts:
- "More than half our bones are in our hands and feet."
- >-
The smallest, the stapes, is in the ear:
about three millimetres long.
- text: "What is the heaviest organ in the human body?"
mechanic: buzzer
readAloud: true
answer: "The skin"
notes: >-
If someone says "the liver": it is the heaviest
internal organ, but the skin wins overall.
explain: >-
The skin: about 2 square metres and
3 to 4 kilograms in an adult.
facts:
- >-
We shed tens of thousands of skin cells
every minute.
- text: "At the summit of Everest, water boils at about..."
choices: ["100 °C", "85 °C", "70 °C", "50 °C"]
answer: C
explain: >-
Around 70 °C: air pressure up there is roughly
a third of what it is at sea level.
Pasta does not cook very well.
facts:
- >-
In a pressure cooker, the opposite happens:
pressure rises and water boils at around 120 °C,
so food cooks faster.The three fields from the console are all here: notes to run the question, explain for the
big screen, facts for the microphone. One file holds both the rules and the material for
hosting them.
What the lying round taught me
The first night exposed a couple of details I had missed. When asked to invent a lie, people weren’t sure how much to write. A word? A phrase? A whole sentence? That prompt needs to make the expected length clear, especially when the invented answers will sit beside the real one.
Capitalisation was another giveaway. Phone autocorrect added capital letters to some team submissions, making them look different from the answers I had prepared. I made every answer display in lowercase, including the real one. The typography should give everyone the same chance of being believed.
Giving teams a way back
Next time I’d like to try more ways to catch up. Most of my scoring was fixed: five points here, ten points there. A bonus for answering quickly would liven up some questions, though speed alone won’t help a team that’s already behind.
I’m also tempted by the interference mechanics in Knowledge is Power: freezing another team’s phone so they have to tap away the ice before they can answer. That would give trailing teams a way to slow the leader down. It all needs playtesting, but the aim is simple: halfway through the show, a losing team should still have a reason to fight for the next question.
The other thing I’d love to add is lighting. I started sketching it out, but I didn’t have DMX equipment or controllable LEDs to try it with. Lights reacting to a buzz, a reveal or a win could bring a little more of the television studio into the room.
Handing it to someone else
A few people asked whether they could use it for their next family party. As a product manager, I know that moment: a working prototype starts to look like a product request.
I knew where to click. I understood the unfinished features and could live with the rough edges of the AI-generated code and interface. Someone hosting their own evening would need to feel just as comfortable, without having built the thing. Even sharing it with friends and family means doing that extra work.
There are commercial tools for this kind of game, but I like how this one turned out, simple visual style included. If more people ask, I might host it, or package it as something they can launch themselves. Either way, the next version has one job: give another host the same confidence I had behind the console.