Josh Stiles

Principal API Developer

Systems Engineer

Software Architect

Algorithms & Data Structures

Performance Optimizations

Josh Stiles

Principal API Developer

Systems Engineer

Software Architect

Algorithms & Data Structures

Performance Optimizations

Lean: I Built a Game Where Changing Your Mind Is the Whole Point

July 4, 2026 Projects

A self-contained Go web app for low-stakes team debates — and what Stanford political science accidentally has to do with ice cream.

Picture this: your team is fifteen minutes into a genuinely heated argument about which single ice cream flavor humanity should keep if all the others were deleted. Someone has just made a surprisingly compelling case for vanilla as “the infrastructure flavor.” Someone else is reconsidering everything they believed about strawberry. Nobody’s feelings are at risk. Nobody’s project is on the line.

That’s Lean — a little web game I built for exactly this. A group joins a room with a 4-letter code, everyone secretly votes on a trivial question, two random people have to make their case, the room debates, everyone gets a final chance to lock in — and then the reveal: an animated chart replaying how the room’s opinion moved over the course of the argument.

The twist that makes it work: there’s no winner. Nobody scores points for being right, because there is no “right.” The thing the game celebrates — literally, with end-of-session awards — is movement. The top award, “Open Mind,” goes to whoever reconsidered the most.

Why build a game about changing your mind?

Three ideas collided into this project.

Icebreakers work, but most of them are cringe. The research on this is more solid than the trust-fall reputation suggests: icebreakers measurably help with what organizational psychologists call psychological safety — the shared sense that it’s okay to speak up, question, and be wrong in front of your team, which Amy Edmondson’s work links to more honest and effective teams. There’s even a neat mechanism buried in the literature: people who don’t speak in the first few minutes of a meeting tend not to speak at all. Lean forces everyone to take a position — privately, cheaply — in the first sixty seconds.

Disagreement is a skill, and you get better with reps. Harvard’s Julia Minson, who studies how people engage with opposing views, argues that practicing on small, trivial disagreements is exactly what prepares you for the big frazzling ones. Her research also shows we systematically overestimate how unpleasant disagreement will be — when people actually engage, the other side usually turns out more reasonable than expected. Arguing about pineapple pizza is a practice field for arguing about architecture decisions.

Changing your mind should be high-status, and almost nowhere is. The psychology literature on intellectual humility — recognizing that your beliefs might be wrong and updating when warranted — ties it to better learning, better relationships, and more tolerance for people who disagree with you. It also notes the obvious problem: our norms reward being right and punish backing down. So Lean inverts the reward. Votes stay completely hidden until the reveal (so you can’t just drift toward the crowd), and the awards at the end are all warm: “Open Mind” for the most reconsidering, “The Scenic Route” for wandering the options and landing back home, “Quiet Conviction” for holding a lean all session. There’s no award for persuading people — I deliberately left “who changed whose mind” out of the stats, because the moment you score persuasion, people start debating to win instead of to think.

The part where I accidentally rebuilt Stanford’s methodology

Here’s my favorite thing I learned while writing this post. The loop at Lean’s core — secret vote, structured discussion, second vote, compare — is a miniature version of deliberative polling, a method political scientist James Fishkin invented in 1988. Fishkin’s version polls a representative sample on real policy questions, has them deliberate in small groups, then polls again. After running it over a hundred times in dozens of countries, the findings are remarkably consistent: deliberation reliably shifts opinions, the shifts persist, and — the finding I find most striking — the process measurably depolarizes participants.

I did not set out to build the party-game version of a Stanford research instrument. But the structure converged for the same reason: if you want to know what a group actually thinks, you have to separate the first instinct from the considered position, and the only way to see the difference is to measure both. Lean’s reveal chart is just a before-and-after poll with suspense and better colors.

The questions are designed for this too. Every prompt is trivial on the surface with something real underneath — “one flavor survives” is secretly about scarcity, “is a hot dog a sandwich” is about definitions, “everyone gets the same indoor temperature” is about who bears the cost of a shared standard. The game tags each question with its hidden layer, subtly, so the debates have somewhere to go once the jokes run out.

The build: one Go binary, zero dependencies

The engineering goal was the same as the game-design goal: no ceremony. The entire thing is a single self-contained Go binary — standard library only, frontend embedded with embed.FS, rooms held in memory, realtime updates over Server-Sent Events. No database, no build step, no npm. go build, copy one file to the server, done.

A few decisions worth writing down:

SSE over WebSockets. I wanted an excuse to use WebSockets and this wasn’t it. The data flow is almost entirely one-directional — the server pushes room state, clients send occasional tiny POSTs (vote, advance). SSE handles that with plain HTTP, automatic reconnection built into EventSource, and no upgrade dance. The one gotcha is reverse proxies love to buffer SSE streams into uselessness; the server sends X-Accel-Buffering: no and the nginx config needs proxy_buffering off and a long proxy_read_timeout. (Caddy just works.)

In-memory rooms as a feature. Rooms are a map[string]*Room behind a mutex. A restart drops live games, idle rooms self-evict after 90 minutes, and nothing is ever written to disk. For an icebreaker game, ephemerality isn’t a compromise — it’s a promise. Nobody’s hot takes about chocolate are being logged.

The host is the pacemaker, with a safety net. Every timed phase can end two ways: the clock expires, or the host taps to move on — whichever comes first. The host can accelerate but never drag. After playing real rounds, I extended this further and gave the host more control over time mid-game, because real groups don’t debate on a fixed schedule: some questions die in forty seconds and some need the full clock plus extra. Auto-advancement also pauses whenever the host disconnects, so a dropped phone doesn’t let the game run away without its moderator.

Identity in localStorage. No accounts. Your player ID lives in your browser; refresh or briefly lose signal and you resume exactly where you were. Latecomers can join mid-round but only participate from the next question — they spectate the current one, which turns out to be a nice onboarding: you watch one reveal and immediately get why the hidden votes matter.

The signature piece is the reveal itself — an animated SVG chart that replays the round’s vote timeline. Every vote change during the debate was snapshotted server-side, so the chart draws the actual story of the argument: lines drifting as people waver, a deliberate deceleration near the end for suspense, then the final standings. It’s the payoff the whole design funnels toward, the moment the room finds out whether anyone budged.

Open by design

Lean is open source — the code, the question bank, all of it: https://github.com/programmerstilesj/lean

I thought briefly about whether a project like this needs “protecting” and concluded the honest answer is that game mechanics can’t really be owned — copyright covers my code and my questions, not the idea of vote-debate-revote, and that’s fine. Fishkin got to the mechanism thirty-eight years before I did anyway. If someone clones it, the dated repo and this post are my proof of authorship, and the idea spreading is sort of the point of an idea like this.

If you try it with your team, I’d genuinely love to hear which question started the best argument. My money stays on the ice cream.

Lean runs at lean.stilestech.com. It’s a single Go binary; the README covers deployment with systemd behind nginx or Caddy in about ten lines.

Tags:
Write a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.