Choose your own keynote: scverse conference 2026
My keynote at the scverse conference 2026 (12–14 October, DTU, Copenhagen), presented as a pixel-art side-scrolling game. There were no slides. I walked around a pixel version of the venue, and the audience voted on their phones for which topic came next.
Play the game in your browser. It needs no install and no sign-in.
| Key | Does |
|---|---|
| ← → | Walk, choose and step through the talk |
| Space / Enter / B | Take action: talk, open doors, poke things |
| F | Full screen |
| R | Back to the menu |
Each room in the venue holds one topic:
- 🎓 Why bother writing software? (the opener, in the lecture theatre)
- 🧬 Community building with nf-core
- 🦀 rewrites.bio
- 🤖 Building tools for agents
- 📊 MultiQC
- 🎮 Side projects
- 📚 Building awesome docs sites
There are easter eggs hidden around the venue. Have fun finding them!
- 🗳️ Live ranking. The audience scanned a QR code and ranked the topics on their phones. Bars beside the game showed which room was most wanted next.
- 🙋 Questions. People sent and upvoted questions. When I put a question on screen, a character in the game walked up with a "?" to ask it.
- 🎉 Reactions. Thumbs, hearts and party poppers from phones floated up over the game. When enough came in at once, the pixel crowd stood up.
All of the code was written by Claude Opus 5.5. It is plain HTML, CSS and JavaScript, and all the art is drawn in code. There is no build step and there are no image files. A small Cloudflare Worker synced the votes and questions during the talk. Now the game runs on GitHub Pages with the live features off.
Open docs/index.html in a browser. That's it.
To run it with the live features, start the Worker locally:
cd worker && cp .dev.vars.example .dev.vars && npx wrangler devThen open the stage at http://localhost:8787/?stage&key=dev, the audience page at /join/ and the moderator page at /mod/?key=dev.
Deploying, presenting and testing
docs/: the static site.index.htmlis the game,content.jsholds the talk's content (characters, topics, beats),places/has one script per room,join/is the audience page andmod/is the moderator page.worker/: the Cloudflare Worker and one Durable Object that holds the live state. It also servesdocs/.
| Address | Who | What |
|---|---|---|
/ |
Anyone | The game |
/?stage&key=KEY |
Presenter, on the laptop | The game plus QR code, ranking bars and upcoming questions |
/join/ |
Audience | Rank the topics, send and vote on questions |
/mod/?key=KEY |
Presenter, on a phone | Put questions on screen, mark them answered, dismiss them |
The presenter key and the Worker's address go in .env, which git ignores:
cp .env.example .env
sed -i '' "s/^PRESENTER_KEY=.*/PRESENTER_KEY=$(openssl rand -hex 24)/" .env
cd worker && npm install && npx wrangler login && npx wrangler deploy
sed -n 's/^PRESENTER_KEY=//p' ../.env | npx wrangler secret put PRESENTER_KEYPut the printed address in KEYNOTE_URL in .env. Run npx wrangler deploy again after each change. A deploy drops every phone for a moment, so don't deploy during the talk.
Run ./present.sh (needs gum) and pick Start the talk. It opens the stage and copies the moderator link to the clipboard, so the key never shows on screen. Run it before the projector mirrors your screen. Press F for full screen, reset the rehearsal votes, and open the moderator link on your phone. The dots turn green when everything is connected. If the connection drops, the game carries on.
npm install && npm --prefix worker install && npx playwright install chromium # once
npm testThe Playwright tests play the game from disk, then drive the stage, two phones and the moderator page against a local Worker. Add ?debug to the game's address to skip the intro and expose window.__game and window.__live. Limits (question length, cooldowns and so on) are at the top of worker/src/worker.js.
Made by Phil Ewels. Fonts: Silkscreen and VT323, SIL Open Font License 1.1. QR codes: qrcode-generator by Kazuhiko Arase, MIT licence.

0 comments
log in to comment.