Nodal Strike
A browser team shooter built to be fair over the internet, and a template for building your own multiplayer game.
A multiplayer shooter that is also a template
Nodal Strike is a browser-based 5v5 team deathmatch shooter, and it is the first game built for Nodal Play. It has two jobs. As a game, it is a quick, readable shooter you can open from a link, play offline against bots, or share with friends through a six-digit room code. As a template, it is a worked example of how to build a multiplayer game that stays fair and smooth over the internet, with the netcode separated from the game rules so it can carry other genres: battle royale, capture the flag, zombies or racing. It was built on stream by vAlentino718 with Claude and Codex agents, and you can play it at nodal-strike.uzig718.workers.dev.

What you can do in it
- Modes: offline against zero to nine bots, online with six-digit room codes, a public server browser, spectator mode with a killcam, reconnect after a dropped connection, and host controls for restart, kick, bots and settings.
- Maps: four. Industrial is a fenced compound with long halls and container rows. Outpost is a desert town at golden hour with a sniper catwalk. Compound is a two-story warehouse and offices with a central bridge. Timberline is a forest clearing split by a river with a ruined cabin and a hunting tower.
- Weapons: twelve, from a sidearm and a carbine to shotguns, SMGs and snipers, several modeled on familiar real-world archetypes, each with its own timings and spread.
- Teams: up to ten fighters, five per side, with bots filling empty slots.
Inside Nodal Play, a streamer’s browser creates a private room with bots named after the room, and everyone in the room is launched into the embedded game after a countdown. The game exposes a small room API and posts two messages to the platform (nodal:match-ended and nodal:exit) so the host can vote on the next game.
How the netcode works, in plain language
Online shooters feel good only if they hide the delay between your keypress and the server’s answer. The project’s netcode document explains the approach used here, which follows well-known techniques from the Source and Quake traditions.
The server decides everything
Clients send only inputs: movement, aim and button presses. They never send positions, hits or damage. The same room code runs in three places: a Cloudflare Durable Object for online rooms, a Node server for local development and long streams, and a Web Worker inside your browser for offline play against bots. That last one matters: offline play uses the real protocol, so playing against bots tests the real code path.
Prediction and reconciliation
Your own movement is predicted locally the instant you press a key. The server periodically sends the last input it processed, plus your exact movement state. The client rewinds to that state, replays the inputs the server has not acknowledged yet and, if the result differs from what was on screen, blends the difference away over about a tenth of a second. Because both sides do the same arithmetic with float32 rounding and quantized view angles, results are bit-identical, and a test asserts zero corrections over four seconds of strafing and jumping. Errors bigger than two meters, such as a respawn, snap instead.
Seeing other players
Other players are drawn slightly in the past, interpolated between server snapshots. The delay adapts to measured arrival jitter and is typically 40 to 70 milliseconds. The clock never warps by more than six percent, and extrapolation is capped at 100 milliseconds so a stall does not send players flying.
Fair hits with lag compensation
Each shot carries the time of the frame the shooter actually saw. The server keeps 64 ticks of player hitbox history, rewinds every target to that moment (clamped to a 200-millisecond window) and casts the ray against head, torso and legs. Aim comes from the server-simulated view angles of the same input, never from the client. Weapon spread is seeded by the shooter, the tick count and the weapon, so the client’s tracers match the server’s hits, and a modified client cannot pick a lucky roll.
Small packets
Snapshots are binary and delta-encoded against the last frame the client acknowledged. Only changed fields are sent, using a bitmask, new entities are sent in full and removed ids are listed. Entity types are declared once as schemas, so adding a flag, a zombie or a vehicle means adding a schema rather than rewriting the protocol. Events such as shots, hits and kills travel in a separate message, tagged with the tick on which they happened so remote tracers leave the gun of the interpolated body.
Why the uplink is 20 Hz
Inputs travel at 20 Hz even though the simulation runs at 60, with each packet carrying every command created since the last one. The reason is cost: the free hosting plan counts incoming WebSocket messages at 20 to 1 against a daily request budget, which works out to about 2.7 hours per day of full ten-player lobbies. On a paid plan or a self-hosted Node server the rate can be raised to 60, and for long streams the project suggests running the Node server behind a free tunnel.
Safeguards against cheating and abuse
- An anti-speed-hack credit budget means a client can never exceed one command per tick on average.
- Messages over four kilobytes are rejected and per-connection message rates are limited. Chat is rate-limited and sanitized.
- Room creation is limited to six rooms per ten minutes per hashed IP address.
- Reconnecting uses a 128-bit token and keeps a player’s slot for sixty seconds.
- Only a keyed room owner is host, so ordinary players never get admin powers.
The document is honest about the limits. A low-ping cheater could shoot up to 200 milliseconds into the past, because the rewind is not yet clamped to measured round-trip time. Players are simulated in join order within a tick, so same-tick trades favor the earlier player. Weapon spread could be seeded with a server-only value for competitive integrity. WebSocket runs over TCP, so a lost packet stalls everything behind it for one round trip, and a datagram transport would help on hosts that support it. And there is no player-to-player collision, because adding it would cause mispredictions. A list of known weaknesses next to the fixes is more useful than a claim of perfection.
Testing and tools
The repository ships about 180 automated tests across 20 test files covering the codec, delta compression, the input queue, interpolation, deterministic prediction, the room logic, bots and the server adapters. A load-test script drives ten headless clients and reports round-trip time, snapshot rate, bandwidth per client and the largest gap between snapshots. A smoothness script runs the real interpolation code at 144 frames per second and prints discontinuities. In the browser, adding ?netsim=150,20 to the address simulates 150 ms of round-trip delay with 20 ms of jitter, and pressing F3 shows a net graph with ping, jitter, interpolation delay, snapshot rate, bandwidth, corrections and frame-time statistics.
Using it as a template
The template guide has recipes for adding a weapon, a map (including imported GLB maps), a game mode (free-for-all in full), capture the flag as an end-to-end new entity type, domination zones, round-based modes, a zombies co-op mode, a battle royale with interest management and a zone, and vehicles. It also states the rules that keep netcode correct: shared simulation code must be deterministic (no random numbers, no wall-clock time, no frame delta), anything the client predicts goes in the private block of the snapshot, and the protocol version must be bumped whenever the wire format changes. Those rules are the real value of the template: they are the lessons that agents tend to violate when left alone, written down so they stop doing it.
Assets are CC0 or properly credited glTF characters and animation libraries, with a licence checklist in the repository. If you want to see how agents are directed on a project like this, read The vibe-coding workflow, and for the tools that keep several agents from colliding on one repository, see AgentBoard on the Nodal site.

Status
Nodal Strike is playable now, offline and online. The platform handoff was tested locally and a two-player live check on the arcade was still pending in the project notes, so expect rough edges. The next idea on the list is a zombies variant built on the same template. Follow along on the livestream or in the Discord.