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 ./games

Serves every HTML game in the folder. Open it in two windows, or send the link to a friend.

Star Squad, three browsers in one room. Recorded from real play.

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

dots.html
<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. 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. 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. 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.

How it works, in detail

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

Bring your own engine A 3D game with three.js

game.js
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.