Post

Roll the Dice — When Your Kid Needs a Dice and You Have a Terminal

My son wanted to play a board game. We had one dice. I had Claude Code open. Twenty minutes later we had a full dice roller with dramatic music, 3D effects, and a competitive mode we didn't plan for.

This post was written with Claude Code (Anthropic's claude-opus-4-6 model).

I pulled my trusty coding buddy Claude into a Sunday afternoon dice emergency and we shipped a whole web app before the board game got cold.

My son wanted to play a board game. We only had one physical dice. Instead of going to find more, I opened Claude Code and built a web dice roller with 3D animations, 10 random dramatic soundtracks, and a competitive scoring mode. The whole thing took about 30 minutes.

Live: dice.dinhnn.com

Fun fact: while writing this post I learned that the correct singular form of “dice” is actually “die.” But this is a fun post about rolling dice with my kid, not a grammar exam. So “one dice” it is. 🎲


Sunday afternoon. My son pulled out a board game and wanted to play. We dug through drawers, checked old game boxes, looked under the couch. One dice. Just one.

The game needed more. Or at least, rolling one dice repeatedly was slow and boring for a kid who wanted action.

I could have searched “dice roller” on Google. There are hundreds. But I had Claude Code already open on my laptop, and the thought crossed my mind: how fast can we actually build one?


The first version was simple. A page with 3D CSS dice, a roll button, and some confetti when you get a result. Pick 1-5 dice, hit the button, wait for the animation.

But “wait for the animation” turned out to be the fun part. I added a random roll duration (3-12 seconds) so you never know when it’s going to stop. Then dramatic background music using Web Audio API, procedurally generated so there’s no audio file to load. Ten different styles that get randomly picked each roll: drumroll, horror suspense, siren, heartbeat, epic orchestra, retro game, tribal drums, space laser, thunderstorm, and circus.

The music intensifies as the timer progresses. By the 80% mark, the screen is shaking, lightning is flashing, and the dice are spinning faster. It’s ridiculous. My son loved it.


After a few rounds of just rolling dice and laughing at the effects, my son said: “let’s see who gets more points.”

So I added a battle mode. Add player names, take turns rolling, scores tracked in a table. It took maybe 5 minutes to add because the rolling logic was already there. Just needed a player list, turn rotation, and a scoreboard.

The app now has two modes:

  • Free Roll — just roll dice, no strings attached
  • Battle Mode — add players, configure dice count, take turns, track scores with a live scoreboard

Then it kept growing. My son wanted to see who’s winning at a glance, so the scoreboard got sorted by points with the current player highlighted. He wanted to play again without re-entering names, so I added a “New Game” button. He accidentally refreshed the page and lost the player list, so I added localStorage to persist settings.

Every feature came from a real moment of “wait, it should do this too.” None of it was planned upfront.

We kept playing the board game the whole time. I was building the dice roller on my laptop while we played, shipping features between turns. By the time the game ended, the tool was done too.


There is no stack. It’s a single HTML file. Inline CSS, inline JavaScript, zero dependencies, zero build step. The “backend” is Cloudflare Pages serving a static file.

Some things worth noting:

  • 3D dice with CSS transform-style: preserve-3d and six faces positioned with translateZ/rotateX/rotateY
  • Web Audio API for all sound, no audio files. Oscillators, LFOs, noise buffers, and gain nodes wired together differently for each of the 10 music styles
  • Spacebar as a dual-purpose key: starts rolling when idle, force-stops when rolling. Same for clicking the button
  • Battle mode with a start/edit flow: configure players and dice count first, then play. Scoreboard sorted by points, auto-advances turns
  • localStorage saves everything: mode, dice count, players, sound toggle. Refresh-proof
  • Vietnamese UI with Google Fonts that actually support Vietnamese diacritics (learned this the hard way when Bangers font turned all the text into boxes)

I described what I wanted in Vietnamese. Claude Code wrote all the HTML, CSS, and JavaScript. When something wasn’t right, like the font not rendering Vietnamese characters, or the timing feeling too predictable, I gave feedback and Claude fixed it.

My role was product manager and QA tester. My son was the primary stakeholder.

The whole conversation was maybe 30 back-and-forth exchanges. Most of my messages were one line: “make the gap bigger”, “the font is broken”, “add battle mode”, “save to localStorage”, “deploy to Cloudflare”. Claude handled the rest.


The interesting thing wasn’t the dice roller itself. It’s that the gap between “I wish I had a thing” and “I have the thing” has gotten absurdly small. A year ago, I’d have Googled for a dice roller, settled for something close enough, and moved on. Today, I built exactly what I wanted, customized for my kid, deployed to a URL I can open on my phone, in the time it would have taken to evaluate three existing options.

The board game got played. And somewhere between turns, a custom dice roller got built, iterated on, and deployed. My son asked me to bookmark it. I’ll take that as a win.