SEARCHED AS · "multiplayer room system javascript"
Rooms and join links
A room is created the first time somebody opens the game and joined by everyone who
follows the link. You don't mint codes, store them, expire them or garbage-collect empty
ones. room.code is the six-character code (no 0/O/1/I, so it
survives being read aloud) and room.link is the URL that drops someone into
this room.
The page around your game already renders the code, a copy button, a QR code and the
live player count — so don't rebuild that chrome inside your canvas, it only duplicates
what's above it.
API: room.code, room.link,
room.players, room.onJoin, room.onLeave.
SEARCHED AS · "real-time state sync javascript game"
Shared state vs per-player state
There are exactly two surfaces, with different write rules the server enforces.
room.state is the shared world and only the host writes it
— phase, timers, NPCs, the scoreboard. room.me.setState() is each player's
own slice: their position, their input, their hat.
Both are flat key/value maps merged last-writer-wins; a null value deletes
a key, and nested objects are replaced wholesale rather than deep-merged. Both
onState and onPlayerState hand you the full surface, so a
late joiner renders correctly from the first callback — there is no delta to replay.
API: room.setState / room.onState,
room.me.setState / room.onPlayerState.
SEARCHED AS · "host migration multiplayer game"
Host authority and host migration
The room creator is the host. If they leave, the relay re-elects the oldest remaining
connection and fires onHostChange. Authority also moves without anyone
leaving: a host that backgrounds its tab hands off so the shared simulation doesn't
freeze on a locked phone. Treat room.isHost as a value that can flip under
you at any moment, and never cache it.
The clean way to survive all of that is to never own the loop yourself:
onHostTick starts when you become host and stops when you lose it. Writing
shared state as a non-host throws NOT_HOST rather than silently diverging.
API: room.isHost, room.host,
room.onHostChange, room.onHostTick.
SEARCHED AS · "websocket reconnect game state"
Reconnects, leavers and late joiners
The SDK reconnects on its own with jittered backoff and resumes the same
player id within a 60-second grace window, so a tunnel or a lock screen doesn't cost
somebody their identity mid-match. On resume the server sends the full state again and
the SDK reconciles, emitting the join / leave / host changes that happened while you
were away.
What stays yours is the game-design half: a disconnected player never reports their own
death, so in any last-one-standing mode prune absent ids at a natural boundary — round
intro, match start — or the person who rage-quit wins by doing nothing.
API: room.onJoin, room.onLeave,
room.onError, room.ping.
SEARCHED AS · "multiplayer game leaderboard backend"
Leaderboards
One await, and you get back the player's rank and their best. Boards keep
each player's highest score, so a resubmit never lowers it; for
fewest-moves-style metrics submit an inverted score so "fewer" ranks higher. Submission
is anti-spoof, not anti-cheat — a signed session token, a minimum session age of ten
seconds, a maximum score and a rate cap. Rejections carry a code and a
hint on the error object, so retry on the code rather than parsing text.
In a keyless room the board lives with the room. Deploy under a project and it
persists, and room.game is non-null to tell you which you've got.
API: await room.submitScore(n),
getLeaderboard({ game: room.game, limit: 10 }).
SEARCHED AS · "where to host a multiplayer html5 game"
Hosting and deploy
A deploy is one self-contained HTML file or a whole project — a path→content map with
index.html as the entry, relative imports resolving against the bundle
root, up to 3 MB per file and 12 MB total. No Docker, no pipeline, no domain, no
certificate.
Which URL you share matters exactly once. /g/<hash> is pinned to the
bytes you deployed — right for "play this build", wrong for a link you post, because a
redeploy has a different hash. Deploy under a project and you also get
/p/<slug>, which always mints a room on your latest build, plus
/world/<slug>: one permanent shared room with a public page and a
global board.
Ship it:
curl -F [email protected] https://antics.gg/api/deploy — or
npx antics-cli deploy game.html.
SEARCHED AS · "multiplayer browser game on mobile"
Mobile
Players join by tapping a link. No app store, no account, no launcher — a phone, a
laptop and the one friend on a work iPad all land in the same room. Nothing in the SDK
is desktop-only, and the room page renders a QR code precisely so somebody across the
table can join without you typing a URL at them.
Two mobile facts worth knowing before you ship: drive your loop from
requestAnimationFrame, because timers get starved by touch events; and an
iOS tap is replayed ~100 ms later as a synthetic mouse event, so guard your
handlers or every button fires twice.
Also: deployed games run in a sandboxed iframe —
localStorage throws there, so never key durable data on it.