
Under the hood
One deterministic Go simulation runs everything: solo play in your browser through WebAssembly, and multiplayer on a local host. Rendering never decides an outcome.
- Simulation
- Go 1.27
- Tick rate
- 20 per second
- Client
- React 19, PixiJS 8
- Wire format
- Protocol Buffers
Architecture
Three parts with hard boundaries. The simulation knows nothing about screens, sockets or clocks, so solo and online play can never drift apart.
Simulation
Orders, economy, movement, combat, fog, abilities and objectives. Pure Go, integer fixed-point, stable iteration order.
pkg/sim pkg/content
Host
Validates every command, runs matches and lobbies, writes saves and replays, and sends each player only what their fog allows.
cmd/frontline internal/server internal/fogcodec
Client
Interface, renderer, audio and input. Solo matches run the same simulation in a WebAssembly worker.
client/ cmd/wasm
One rulebook
There is no simplified local game. Skirmish, campaign, co-op and multiplayer all call the same simulation package.
Native and WASM parity
Checks run the same commands natively and in the browser worker and compare results. Closing the remaining packaged-build gaps is open work.
Intent, not outcomes
Clients submit orders. Damage, credits, research and victory only ever come from the simulation.
Fog on the wire
Snapshots are filtered per player before they leave the host. Hidden units are never sent and then merely hidden.
Determinism
Given the same starting state and the same commands, every machine computes the same match, tick for tick. That makes saves exact, replays tiny and desyncs findable.
Fixed-point everywhere
HP, money, speed and range are integers scaled by 1,000. A Ranger squad's 300 HP is stored as
300000.Twenty ticks a second
Every timer is a tick count. A 10-second build is exactly 200 ticks on every platform.
Stable order
Entities update in a fixed order. No map iteration, goroutine scheduling or wall clock can change a result.
Complete saves
A save holds the whole state at a tick boundary: queues, reservations, projectiles, cooldowns, AI knowledge and random state.
Replays are command logs
Seeking restores the nearest snapshot and simulates forward. Rewards and reinforcements are never paid twice.
Versioned rulesets
Matches record their ruleset version and hash. Incompatible saves are kept and explained, never silently deleted.
Rules as data
Units, weapons, buildings, upgrades and armor live in one validated file. Change a weapon once and every unit that carries it changes with it.
// pkg/content/rules.json, one of 76 unit entries
{
"id": "US.tank", "name": "Sentinel tank",
"cost": 1300000, // 1,300 credits
"build_ticks": 600, // 30 seconds
"hp": 1400000, "armor": "heavy",
"supply": 4, "tier": 1, "speed": 2300, // 2.3 tiles per second
"weapon": "TANK", "producer": "factory"
}
Validated before play
cmd/contentcheck rejects missing references, illegal targets, cyclic tech, negative prices and duplicate IDs.
Maps and missions too
Layouts, objectives, briefings and triggers are JSON in content/, using a bounded trigger library. Imported files never run code.
Stable IDs
Role IDs like IR.launcher never change, so names and art can evolve without breaking saves.
This site reads it too
Every roster and table on these pages is generated from the same file by site/scripts/build.mjs.
Art pipeline
Units and buildings are modeled in Blender and rendered from a fixed elevated camera into sixteen directions, with separate layers the renderer combines at runtime.

Every state, not just idle
Units need idle, move, aim, fire, damage and destruction poses. Buildings need foundation, construction, low power, disabled, capture and rubble states.
Silhouettes first
Stylized, classic-RTS readability over photorealism. A tank must read as a tank at normal zoom.
A manifest accounts for everything
Every roster entry, building state, portrait, cursor and effect has a manifest ID, and missing art blocks a finished-presentation claim.
Reproducible renders
Model scripts live in assets/pipeline/blender. One heavy render job at a time keeps a 16 GB machine usable.
Repository map
Where things live, so you can find your way to the part you want to work on.
pkg/sim/ deterministic simulation: the game itself pkg/content/ rules.json and content loading cmd/frontline/ local host: matches, lobbies, saves, replays cmd/wasm/ the simulation compiled for the browser worker cmd/contentcheck/ content validator cmd/simcheck/ simulation checks internal/ server, storage, fog codec, view protocol protocol/ frontline.proto wire schema client/ React + PixiJS client, runtime adapters, tests content/ maps, missions, environment dressing assets/pipeline/ Blender models, audio, UI and manifest tooling docs/ architecture, protocol, status and per-system notes outputs/ the authoritative game design document site/ this websiteRead the architecture notes
Verification
Claims need evidence. Tests, browser runs and full bot matches produce recorded results, and a failure is kept on record rather than quietly re-run until it passes.
Some limits need people and hardware, not more code: a second physical machine for LAN, Safari, reference laptops, and human balance sessions. That's where playtesters come in.