I did not seem to be able to play this game at all, unfortunately.

ETA is about 2 weeks lmao, finished 10 million this time yesterday in just 4 days, you just missed out! So in 25 hours 5 million clicks have been made 🫠 Here's the replay: https://million.wayfarer.games/replay
If I had outright said it was banned, and told people when they were banned, they would attempt to get around it! By doing it this way, people assumed I wouldn't have any autoclick detection so only did it the naive way. I'm confident that the top 5 scores were all human clicks, which means the whole thing worked as intended!
I'll run some tests on the GUI issues, yeah, I'm really curious too 😂
Ah I think you probably just missed it roll over to zero 😅 there's a replay here: https://million.wayfarer.games/replay
There is auto clicker detection, it measures consistency over time, so it'll get them eventually, and remove them from the leaderboard :)
I wondered if someone using an auto clicker would show up! I've been keeping an eye on yours, I've got you in a moderation view 😂 you won't see anyone else that high because your score is not that high! You're not on the leaderboard 😉 your score was caught at around 290k and you were knocked down to 50k and stopped contributing to both the main countdown and the leaderboard! Everything appears to continue to work to stop people figuring out they were banned and changing their behaviour lol, it has been very effective.
Thank you for the stress test 🙏 I suspect a lot of the issues you faced (except the audio and gui) were actually because you were banned. You'll be forever immortalised in the ban list ♥️ I can't change the end stats to include you now unfortunately, but I would if I could!

The backend is mostly a single script (Lua in Valkey, driven by a Phoenix server) that processes every click one at a time. That means validating the round, rate-limiting, and decrementing the countdown, so there's exactly one winner and no lost or double-counted clicks! There's a bunch of extra stuff around stats, username moderation/autoclicker detection, that sort of thing, but the bulk of it is that one script. I wrote a full post about it here: https://wayfarer-games.com/blog/one-button-mmo/
Here's a post explaining the tech 😁 https://wayfarer-games.com/blog/one-button-mmo/
Agree about it's questionable game status, but people seem to be having fun and it does have a goal, so maybe it counts!
Hey! I made Ten Million Clicks Together for the GMTK jam, a game where everyone clicks one button that counts down from 10,000,000 to zero.
That's the whole pitch. There's one button. You press it. The number gets smaller.
This sounds like it should be the easiest game I've ever made 😂
It is not.
I'll let you in on a secret: "multiplayer" really means "arguments about what order things happened in". A normal clicker keeps its number on your device and updates it the instant you press the button. A shared clicker has to answer a much nastier question: what does "the number" even mean when thousands of people are changing it at once, all with different connections, all seeing a slightly different version of the game?
Nearly every decision in this project is a tradeoff between three things: being correct, feeling instant, and not melting the server, and that's usually a "pick two" kind of situation...
The server has to own the final number, obviously. If every browser got to decide what counted, cheating would be hilariously easy!
Unfortunately, a round trip to the server takes time:
press → send click → server updates → response returns → update screen
Even a good 80ms connection makes that feel a bit sticky, and on a bad connection it feels completely broken.
The fix is client-side prediction - the same trick shooters use to move your character before the server agrees. When you click, your "contribution" number and combo meter update immediately, and the server catches up a moment later.
But you can only predict things you're allowed to be temporarily wrong about:
I also smooth the displayed countdown towards each new server value instead of snapping it. If 40 other players clicked between updates, the number rolls down through the difference, which feels snappier and more like "individual clicks are updating this number". They very much are not.
The combo meter follows the same rule. The game can predict that the meter is full, but the ×2 multiplier doesn't switch on until the server confirms it. That means there is a tiny delay at the exact moment the multiplier activates, so you never see a ×2 contribution that later gets corrected back down to ×1. In practice though, you're never going to notice this!
Most scaling advice boils down to "divide the work between machines". That doesn't really work here, because we have one value that every single player is touching. The countdown itself can't be split into ten independent counters, because then which counter gets the final click? How do all ten agree the round is over?
So I made scoring a single long, messy script that runs on a single thread and is the "source of truth". Every click runs through one small all-or-nothing operation that validates the round, applies the rate limits, works out the multiplier, reduces the countdown, updates your contribution, moves your leaderboard position and bumps a version number.
Usually, you'd never want to do that. I'm sure someone reading this just threw up a little. It does actually work here, though, because the operation is tiny, lives entirely in memory, and never waits on anything halfway through. That means every accepted click has exactly one place in the order!
Sending one network message per click is wasteful - people can click fast, and every message carries the same protocol overhead. But waiting around to build big batches is worse, because it increases the amount of unconfirmed stuff on your screen.
So we compromise: the client waits a tiny window and sends up to 16 clicks in one compact message. At normal speeds, most batches contain just one click. During a frenzy, it sends a few clicks per message. The delay is too short to actually feel, but it removes a bunch of work that happens when the system is busiest.
Batching creates another problem: networks are really annoying.
What happens if you send a click, the server applies it, and the reply gets lost on the way back? Your browser only sees a timeout. If you send the click again... have you now contributed once or twice?
You can't fix that with "retry and hope". Every click gets a sequence number, and the server remembers the last one it accepted from you. Batches look like this:
stream: abc123 first sequence: 481 click count: 6
That means "clicks 481 to 486". If the response disappears, the client sends the exact same batch again. The server spots that it has already seen those numbers and returns the original result instead of scoring them twice.
There are a couple of extra wrinkles. If the browser reconnects and finds the server further ahead than expected, it uses the server's number and carries on. And if the round ended while the clicks were travelling, they are thrown away.
The alternative is choosing between lost clicks and duplicated clicks every time a response goes missing, but I'm pretty sure that would be bad in this sort of game 🤔
The final click is the most interesting problem. When I say interesting I do of course mean "aaaaaaaaaaaaaaaaa[...]"
When the countdown is at 1 and two players click at almost exactly the same time, you might think to do this:
Player A reads 1 Player B reads 1 Player A writes 0 and wins Player B writes 0 and also wins
Congratulations, we now have two winners 🫠
Instead, that one all-or-nothing scoring operation handles every part of the process, so no other click can sneak into the middle. By the time the next player's click hits the code, the round is already over. A nice, simple, if messy, fix.
The obvious realtime implementation is to broadcast the new countdown to everyone after every accepted click.
That works brilliantly with three players and becomes increasingly stupid as the game gets popular. If 2,000 clicks land in one second, sending 2,000 updates to every connected player doesn't make anything smoother - browsers can't meaningfully display 2,000 intermediate states anyway. They'd just burn CPU decoding messages and rewriting the same number over and over.
The trick is noticing that different information has different urgency:
The high-frequency messages themselves are fixed-size binary frames rather than JSON, so I'm not shipping the words "remaining" and "players" thousands of times a second. The entire global state fits in 39 bytes.
Yes, that means spectators can be up to 50ms behind the newest countdown, and the leaderboard up to 200ms behind. Nobody can tell, and neither delay changes a scoring decision, because those displays are never used as authority. "Realtime" doesn't mean "send everything instantly" - it means each part of the screen is fresh enough for what it's for.
Rate limiting one player is easy. It stops a single browser from spamming thousands of clicks per second, but it does nothing about someone opening fifty tabs with fifty identities.
The obvious next step is a limit per network - and that's a trap. Hundreds of legitimate players at a school, office or event can all appear to come from the same place. A strict per-network limit treats a successful real-world crowd exactly like an attack, which is a terrible reward for going viral in a classroom.
So the network allowance stretches: the more distinct, recently active players on a connection, the more capacity it gets, up to a hard ceiling. One person can't multiply their throughput by opening more tabs, but a genuine crowd sharing a connection gets room to play.
We have one input and one objective, and that simplicity exposes every tiny little flaw. There's no room for the shared number to be approximately right - everyone has to agree that one ordered sequence of changes happened, even when messages get delayed, duplicated and lost along the way.
Every decision here comes from asking the same question: does being wrong here change the result?
yeah it's not easy, and this is worst-case scenario for networking! I wrote a blog post if you're interested :) https://wayfarer-games.com/blog/one-button-mmo/
It didn't actually take as long as you'd think 😂 here's what's going on under the hood: https://wayfarer-games.com/blog/one-button-mmo/
I wrote a blog post about it! https://wayfarer-games.com/blog/one-button-mmo/
A lot of trial and error with custom CSS:
.game_frame
{
background:none;
}
.html_embed_widget button.button.load_iframe_btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
width: 300px;
height: 50px;
font-size: 0;
}
.html_embed_widget button.button.load_iframe_btn > .svgicon {
flex: 0 0 auto;
margin: 0;
}
.html_embed_widget button.button.load_iframe_btn::after {
content: "Get clicking";
font-family: "Cracker Winter", sans-serif;
font-size: 24px;
line-height: 1;
}