Games
My self-hosted arcade got a leaderboard, and now my friends won't stop competing
My pile of browser games became a console-style hub. Then I gave it a shared leaderboard — and a quiet single-player project turned into a competition my friends keep coming back to.
A while back I gathered my scattered browser games into a little console-style hub at games.iameberhard.com — an Xbox-360-era dashboard with a profile, some menu blades, and a built-in waiting-room mini-game. It was a fun afternoon project.
Then it kept growing. More games landed on the shelf, and at some point a single-player toy turned into something my friends actually compete over. Here's how that happened.
From one game to a whole shelf
The hub started with one game. It now has six, plus the little dodger baked into the dashboard:
- Nightfall — top-down zombie survival with endless waves
- Neon Breaker — a glowing brick-breaker
- Iron Line — a tower defense with drifting creeps
- Buzzer Beater — drag-and-release arcade basketball
- Neon Runner — a cyberpunk hover-bike delivery dash
- Planet Chaos Simulator — a sandbox where you rule (or wreck) a living planet
Every one is a single self-contained HTML file — no frameworks, no build step. Adding a game is just dropping a folder onto the server and adding a card to the dashboard. That simplicity is the whole point: each game is small enough to finish in a sitting, and the collection is the reward.
![]()
Make it a competition
Here's the thing that changed everything. Each game was quietly saving your best score to the browser — which meant nobody could ever see anyone else's. My high score lived on my laptop; my friend's lived on theirs. No rivalry, no bragging rights.
So I added a shared leaderboard. You type a name on the way in, and that's your identity across the whole arcade — same name on any device, same profile. No passwords, no sign-up flow, no email. For a few friends messing around, friction is the enemy.
Every game now reports its score to a central board the moment you finish a run. There's a Ranks screen that lists everyone by total gamerscore, medals and all, with your row highlighted.
The goal was never a high-score table. It was the group chat afterward — "wait, how did you get 4,000 on the tower defense?"
![]()
The plumbing behind the scores
None of this touches a third-party service. The leaderboard is the same Raspberry Pi that hosts this blog.
The games are served by a tiny, dependency-free Node static server I'd already written. I taught it a handful of JSON endpoints — log in, submit a score, save a profile, fetch the board — backed by a single JSON file on disk. A few friends generate a trickle of requests, so there's no database to babysit; the whole thing is maybe seventy lines.
Public access rides the Cloudflare tunnel the rest of my setup uses, so there are no open ports and everything is HTTPS. When you finish a game, it quietly POSTs your score home, the server keeps your best, and the next person to open the Ranks screen sees it. That's the entire magic trick.
![]()
Awards, and what's next
Because the scores were already flowing through one place, achievements came almost for free. The server knows everyone's best in every game, so it just checks thresholds and unlocks badges — score 100 in the dodger, hold the line in the tower defense, grow a thriving planet to a few billion. Every new player starts with zero and earns them by playing.
There's something satisfying about a competition you fully own — no accounts harvested, no ads, no platform deciding the rules. Just a Pi in the corner keeping score for a handful of friends.
Next on the shelf: probably a racer, and maybe per-player PINs so nobody can borrow a rival's name and tank their stats. For now, the arcade is open — go set a score and put your name on the board.
![]()
Filed under