# Turning a Socket.IO multiplayer prototype into a Net Forge game

> A Socket.IO prototype relays events between browsers. Net Forge replaces the hand-written relay with an authoritative room that steps one shared simulation, so movement, hits and scores are decided in one place.

Net Forge, the open-source multiplayer browser game engine built for AI coding agents, is published on npm under `@netforge` with source at https://github.com/netnetdev/net-forge.

Source: https://forge.netnet.capital/docs/migrate/from-socket-io-prototype  
Last updated: 2026-10-23. Checked against @netforge/engine 0.2.0.

Socket.IO is a library for "low-latency, bidirectional and event-based communication" between a client and a server, with rooms, broadcasting and automatic reconnection ([Socket.IO docs](https://socket.io/docs/v4/)), and it is a quick way to get two browsers talking. When a prototype outgrows hand-written events, move it to Net Forge: the room host steps one simulation, each browser predicts its own player with the same code, and your rules live in one declarative file.

```sh
npm create netforge@latest my-game -- --template arena --yes
cd my-game
npm run play -- --players 2
```

## Why prototypes move

A typical Socket.IO prototype broadcasts each player's position and lets every browser draw what it receives. That is the right way to start. As the game grows, the same questions come up: who decides a hit, how to stop a client from teleporting, how to hide the wait for the server, and how to keep two copies of the rules in step. Net Forge answers them with one design:

| In the prototype | In Net Forge |
|---|---|
| `socket.emit("move", { x, y })` | Sequence-numbered input commands (move, aim, buttons), quantized so client and server read identical values |
| `io.to(room).emit("state", players)` | Quantized delta snapshots per player, 20 a second in local play |
| Rules in the client, the server, or both | Rules once, in the shared simulation, decided by the room |
| Drawing whatever arrives | The local player predicted and reconciled; others interpolated |
| `socket.join(roomId)` | A room per game. Locally every tab joins the open room; on the hosted service a link with `?room=<id>` joins a specific one |
| Reconnect handling | The room client's connection, on Colyseus |

## 1. Pick the template nearest your prototype

| Prototype | Template id |
|---|---|
| Top-down shooter or `.io` arena | `arena` |
| Co-op against waves of enemies | `survivor` |
| Racing | `racer` |
| Platform race | `platformer` |
| Turn-based or card game | `cards` |
| Party minigames | `party` |

```sh
npm create netforge@latest my-game -- --template arena --yes
```

## 2. Move rules, not messages

You do not port your events. Port what they meant: the things in your world and what happens to them, as declarations in `src/game.ts`.

```ts title=src/game.ts
import { prefab } from "@netforge/engine";

// What your server used to spawn and broadcast is now declared once.
prefab("drone", { model: "style.lowpoly.bat", health: 20, speed: 4.5, radius: 0.35, damage: 5, ai: "chase" });
```

## 3. Check it with bots, then with people

```sh
npm test
npm run play -- --players 2
```

`npm test` plays the game headless with bots and reports kills, rounds, softlocks and the cost per tick. The second line opens two tabs in the same room.

## When to keep Socket.IO

Keep Socket.IO for the parts that are messages rather than simulation: chat, presence, notifications, dashboards or anything outside the game's rules. It also suits games whose state is small enough to send whole. Net Forge's `src/game.ts` may import only `@netforge/engine`, so side channels like chat belong in a service of your own.

## FAQ

### Is Socket.IO a WebSocket library?

Socket.IO can use WebSocket as its transport, but its docs say it is "NOT a WebSocket implementation": it adds metadata to each packet, so plain WebSocket clients and Socket.IO servers do not interoperate ([Socket.IO docs](https://socket.io/docs/v4/)).

### What does Net Forge use for transport?

Rooms run on Colyseus over WebSocket. The local host in `@netforge/kit-play` uses `@colyseus/core` with `@colyseus/ws-transport`, and the browser connects with the Colyseus SDK.

### Do I need to write prediction myself?

No. The template predicts the local player with the shared simulation and reconciles against the room's snapshots. See [Netcode and prediction](https://forge.netnet.capital/docs/concepts/netcode-prediction.md).

### Can I keep my own server?

Net Forge games run on Net Forge rooms. If your game logic must stay in your own server, a room framework such as Colyseus is the better step up from Socket.IO ([Net Forge and Colyseus](https://forge.netnet.capital/docs/compare/colyseus.md)).
