I built Pebble Merge, a physics puzzle game that runs in the browser: drop stones, merge same-colored ones, score points, and try not to stack past the top line.
The part I care about most is the global daily leaderboard. Every day all players get the same seeded board (a new seed rolls at UTC midnight), so after you finish a round you can see where you rank worldwide.
Link: https://pebblemerge.bysoft.site/
Three modes:
- Classic - beat your own best
- Daily - same seed as everyone else, global board
- Zen - no game over, just merge
How the leaderboard handles cheating
The client never sends a score. It sends a merge log. The server replays that log through the real game logic (core.js, the exact file the browser runs) and recomputes the score, then checks:
- the daily seed matches today's UTC seed
- the recomputed score equals the claimed score
- stone mass is conserved across the whole log
- the score is under the theoretical upper bound
- per-IP hourly submission cap
Inflated scores get rejected, and cheating means reimplementing the physics, not editing a number in devtools.
Stack
- vanilla JS + Matter.js for the physics
- static assets on Cloudflare Workers
- Node + Express + Postgres for the score service, on a Synology NAS behind a Cloudflare tunnel
That last one is the only reason a global leaderboard costs me nothing to run: no server bill, and I own the data.
Feedback on the physics tuning and bug reports are very welcome - I would rather hear what feels wrong now than after I add more modes.


Top comments (0)