Open source, MIT
Multiplayer rooms for browser games.
The game runs in the players' browsers. A small Node server keeps everyone in sync. You get rooms, invite links, a lobby, reconnects and smooth movement, and you write no server code.
npx tickcli ./gamesServes every HTML game in the folder. Open it in two windows, or send the link to a friend.
- 0runtime dependencies (the Node adapter uses
ws) - 14 KBroom.js, gzipped
- 960players in 60 rooms on one 6-core server, none dropped
- MITlicense, server included
One HTML file. Two calls.
Every player moves themselves and calls g.me.set. Every screen draws g.players. That is the whole network part.
Game()brings the lobby, room code, invite link, reconnects and a touch pad on phones.- You declare each field's range; the hub refuses any value outside it.
- Other players are drawn a moment in the past and eased between updates.
Save it as dots.html, run npx tickcli in that folder, open it twice. Quick start
<script src="room.js"></script>
<script src="game.js"></script>
<script>
let x = 400, y = 300;
Game({
title: "Dots", size: [800, 600],
multiplayer: { max: 8, player: { x: [0, 800], y: [0, 600] } },
update(g, dt) {
const a = g.axis(); // arrows, WASD or touch
x = Math.min(800, Math.max(0, x + a.x * 250 * dt));
y = Math.min(600, Math.max(0, y + a.y * 250 * dt));
g.me.set({ x, y }); // 1. share where I am
},
draw(g, ctx, w, h) {
ctx.fillStyle = "#0f172a"; ctx.fillRect(0, 0, w, h);
for (const p of g.players) { // 2. draw everyone
ctx.fillStyle = p.me ? "#60a5fa" : "#e2e8f0";
ctx.beginPath();
ctx.arc(p.state.x, p.state.y, 12, 0, 7); ctx.fill();
}
},
});
</script>How it works
No game code ever runs on the server, so a new game needs no server change.
- 1
One browser runs the rules
One player is the host: their browser runs rounds, timers, health and scores. If they leave, another player takes over.
- 2
The hub keeps everyone in sync
A small Node server holds each room's state, the order of changes and the limits. Every message has a size and rate limit.
- 3
Every screen stays smooth
Positions ease between updates, 3D rotations blend. A seat is held 30 seconds after a drop, 5 minutes if a phone switched apps.
Keep the engine you have
Your engine draws and runs its own loop. tickcli adds the lobby and the room around it, and keeps one sprite per other player.
- Phaser
- PixiJS
- three.js
- Babylon.js
- Kaplay
- Your own loop
const g = Game({
headless: true,
multiplayer: { max: 8, player: { x: [0, 800], y: [0, 600] } },
});
// in your Phaser scene's update():
if (g.state === "playing") g.me.set({ x: hero.x, y: hero.y });
g.sync(
(p) => this.add.circle(0, 0, 14, 0xf87171), // joined
(s, st) => s.setPosition(st.x, st.y), // each frame
(s) => s.destroy(), // left
);Games running on it
Every clip is a few seconds of real play in two or more browsers. All of them are in the repo, one HTML file each.
Who it's for
Web game developers
Multiplayer without building and running a game server for every game.
Game jam teams
One HTML file, one link, and people are playing a few minutes later.
People making games with AI
Models write plain HTML and JavaScript well; the network part is what they get wrong. Give yours llms.txt and the laptop-to-live guide.
Sites that host other people's games
The hub never runs game code, and a game page can sit in a sandboxed iframe with no network access.
What it is not for
Ranked play or prizes
The host's browser decides hits and scores, so a player who edits their browser can cheat. Fine for friends, party games and co-op. Not for esports.
One huge room
A room holds 16 players by default. One server runs many rooms; one room is not an MMO. All limits
Make your first room
Two minutes, one file, no account.