OpenFrontIO: self-hosting the browser RTS that rewrote WarFront.io
Project brief: Online browser-based RTS game. Players compete to expand their territory, build structures, and form strategic alliances in various maps based on real-world geography.
At a glance
- What is it?
- OpenFrontIO is the TypeScript fork and rewrite of WarFront.io, a browser-based territorial strategy game with a deterministic core, an AGPL-3.0 licence and a Docker path to self-hosting. The interesting part for engineers is the split between simulation, server and client, not the game itself.
- Who is it for?
- Adopt OpenFrontIO if you want a working, non-trivial real-time multiplayer codebase to read or to run on your own hardware, and you accept AGPL-3.0 plus the asset licence that sits beside it. Do not adopt it if you need a stable plugin API, a documented modding surface or a guaranteed-uptime public server, because the README documents none of those.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What OpenFrontIO actually is, and who the repository is for
OpenFrontIO is an online real-time strategy game played in a browser. The README describes the loop plainly: players expand territory, build structures and form alliances across maps modelled on real-world geography. The repository is a fork and rewrite of WarFront.io, with credit given to the upstream project at github.com/WarFrontIO.
That framing matters, because the audience is not really the player. The player goes to openfront.io and never sees a terminal. The repository is aimed at people who want to run their own instance, change the simulation, or read a full-stack TypeScript multiplayer game that is not a toy. The package name in package.json is openfront-client, and the top level mixes a Vite client, a Node server, a Go map generator, a Dockerfile, an nginx.conf and a supervisord.conf. This is a deployed product with its deployment plumbing committed alongside the source.
The licence is the first thing a commercial team should read. The README states the source is under the GNU Affero General Public License v3.0, and it points at a separate LICENSE-ASSETS file for assets and a LICENSING.md for history. AGPL-3.0 is a network-copyleft licence: if you run a modified version as a service, the obligations follow the service. The README also requires modified versions to keep the copyright notices that currently appear in the footer and on the loading screen, both reading "© OpenFront and Contributors", in reasonably visible locations. That is a concrete constraint on forks, not a formality.
The deterministic core, the server and the client
The project structure section of the README names four directories that explain the architecture: /src/client for the frontend game client, /src/core for the deterministic game simulation, /src/server for the backend game server, and /resources for static assets including maps. A fifth, /zbin, is described as a compact binary wire format for zod schemas, self-contained and zod-only.
The word deterministic is the load-bearing one. A deterministic simulation means the same inputs produce the same state on every machine, which is what makes replays and server-authoritative state possible without shipping full snapshots constantly. The zbin directory suggests the wire format is schema-driven rather than hand-rolled: zod schemas define the shape, and zbin encodes them compactly. That is a reasonable design for a game that has to send frequent small updates, though it couples the protocol to zod and to whatever version of the schema both sides agree on.
There is a real cost hidden here. The README warns that to replay a production game you must be on the same commit the game ran on, and that the gitCommit value can be found at https://api.openfront.io/game/[gameId]. It also states that unfinished games cannot be replayed on localhost. That is the practical consequence of determinism tied to a code revision: change the simulation and old replays stop matching. For a game this is fine. For anyone hoping to treat replays as a stable long-term artefact, it is a limitation to plan around.
Installing OpenFrontIO and running your first local game
The README lists npm v10.9.2 or higher as the only prerequisite, plus a modern browser. Clone the repository and change into it first.
git clone https://github.com/openfrontio/OpenFrontIO.git
cd OpenFrontIOThe installation step is deliberately not the usual one. The README is explicit that you should not run npm install or npm i, and should instead run the project's own script, because it wraps npm ci --ignore-scripts to install exactly the versions in package-lock.json without executing lifecycle scripts.
npm run instThe reasoning given is supply chain risk: ignoring scripts means a compromised dependency cannot run arbitrary code at install time. It is a defensible default, and worth copying in other projects, but it also means any package that genuinely needs a postinstall step will not get it. If something fails later, that is the first thing to suspect.
To run both halves of the game with live reloading:
npm run devAccording to the README this starts the webpack dev server for the client, launches the game server with development settings, and opens the game in your default browser. Setting SKIP_BROWSER_OPEN=true in your environment suppresses that last part. Note the mismatch worth knowing about: the README says webpack, while package.json shows start:client running vite, and the repository carries a vite.config.ts. The dev script itself invokes start:client and start:server-dev, so the effective bundler is Vite.
If you only want one side, npm run start:client runs the client with hot reloading and npm run start:server-dev runs the server with development settings. The server script sets GAME_ENV=dev along with placeholder values for TURNSTILE_SITE_KEY, API_KEY, ADMIN_BOT_API_KEY, DOMAIN and GIT_COMMIT, so a local server starts without real credentials. Those placeholders are named as warnings in the script itself; they are not for production.
To point a local client at the hosted backends, the README gives two scripts. npm run dev:staging connects to staging API servers, and npm run dev:prod connects to production API servers. The stated use case is replaying games, testing user profiles, purchases or the login flow.
Where OpenFrontIO is the wrong tool
The documentation is a README, a CONTRIBUTING.md and a docs directory. There is no published plugin API, no modding contract, and no compatibility promise for anything under /src/core. If your goal is to build on top of the simulation rather than inside it, the repository gives you no stable seam to attach to, and the replay constraint means you cannot even assume a given game state survives a version bump.
Operationally, the project is honest about one failure mode without solving it for you. A search question people actually type is why OpenFront is lagging, and the architecture explains the shape of that problem: a real-time game with a server-authoritative deterministic core is sensitive to round-trip latency, and the client bundle is built with Vite and served through nginx with worker_connections raised to 8192 in the Dockerfile. None of that is a fix for a bad connection, and the README does not document a latency budget, a tick rate, or any client-side prediction strategy.
The Dockerfile is another boundary. It runs npm run build-prod, which after the Vite build executes scripts/buildAssetHashes.ts to emit static/asset-hashes.json and static/core-version.txt. A comment in the Dockerfile states that without copying the scripts directory the image build fails at that step with ERR_MODULE_NOT_FOUND, and that the unit suite cannot catch it because only the container build runs build-prod from a copied tree. That is a useful comment, and also a warning: if you trim the build context, expect the failure the maintainers already hit.
Finally, if you want a single-player game or a static site, this is the wrong project. It is a networked multiplayer service with nginx, supervisor and a Node server in the image.
How OpenFrontIO differs from a static browser game
The obvious alternative is the class of browser strategy games distributed as a single HTML bundle, where the whole game runs in the tab and nothing needs a backend. Those are trivial to host and impossible to cheat-proof, because the player owns the state. OpenFrontIO takes the opposite position: /src/core holds the simulation, /src/server runs it authoritatively, and the client renders what the server tells it. That is why the repository needs a Dockerfile with nginx, supervisor and a Node runtime rather than a static host.
The second alternative is the upstream project this forked from. WarFront.io is credited in the README as the origin, and OpenFrontIO describes itself as a fork and rewrite. Anyone comparing the two is really comparing a rewrite against its ancestor, and the README does not enumerate what changed. That silence is worth noting: if you are choosing between them, the repository will not make the argument for you.
The third alternative is treating OpenFrontIO as a game and playing it at openfront.io rather than running it. Nothing in the README suggests self-hosting is required to play, and the presence of dev:staging and dev:prod scripts shows the hosted backends are the normal path even for developers. Self-hosting is for control and for reading the code, not for access.
Maintenance, upgrades and what the licence commits you to
The repository is not archived and the most recent push recorded is 2026-08-28, which is recent enough that the project is being worked on rather than parked. The release list shows v0.33.12 on the same date, alongside v0.34.0-test-release and a bare test-release tag two days earlier. The existence of a test-release channel is a signal about how changes reach players, but the README does not document a support policy, a deprecation window, or which versions are considered stable.
Upgrade cost is dominated by the replay constraint rather than by dependency churn. Because replays require the same commit, and because the simulation lives in /src/core, any change to that directory is effectively a protocol change for anything that replays or reproduces past games. The Dockerfile pins Node 24 and uses npm ci against package-lock.json, so dependency upgrades are reproducible but also explicit: nothing moves until someone moves the lockfile. The build bakes GIT_COMMIT into the client bundle via a Vite define, and the Dockerfile notes that an empty STRIPE_PUBLISHABLE_KEY is valid, in which case the inline wallet and card flow is disabled and purchases fall back to the redirect flow.
On licensing, the README states AGPL-3.0 for the source and points to LICENSE-ASSETS for assets and LICENSING.md for history. The practical reading is that running a modified OpenFrontIO as a public service triggers the network-copyleft obligations, and that the assets may carry different terms from the code. The README also requires forks to keep the "© OpenFront and Contributors" notices visible in the footer and on the loading screen. None of this is legal advice; if you plan to run a modified instance commercially, read LICENSE, LICENSE-ASSETS and LICENSING.md together and get your own counsel.
Editorial conclusion
Adopt OpenFrontIO if you want a working, non-trivial real-time multiplayer codebase to read or to run on your own hardware, and you accept AGPL-3.0 plus the asset licence that sits beside it. Do not adopt it if you need a stable plugin API, a documented modding surface or a guaranteed-uptime public server, because the README documents none of those. Before you commit, check three things: that npm run inst completes on your Node version, that the Dockerfile build stage resolves scripts/buildAssetHashes.ts, and that your fork preserves the copyright notices the licence section names.
Frequently asked questions
What is OpenFront.io used for?
It is an online real-time strategy game about territorial control and alliances, played in a browser on maps based on real-world geography. The repository also serves as a self-hostable TypeScript codebase for running your own instance.
Is OpenFront.io free?
The source is licensed under AGPL-3.0 and can be cloned and run yourself. The Dockerfile references a Stripe publishable key and notes that leaving it empty disables the inline wallet and card flow, so a hosted instance can offer purchases, but nothing in the README states a price for playing.
Why is OpenFront lagging so much?
The README does not document a tick rate, latency budget or client-side prediction strategy, so it offers no explanation for lag. What it does show is a server-authoritative design with a deterministic core in /src/core and a Node server in /src/server, which makes responsiveness depend on the connection to that server.
How do I install OpenFront.io locally?
Clone the repository, then run npm run inst rather than npm install, because the script wraps npm ci --ignore-scripts to install exact versions without running lifecycle scripts. npm v10.9.2 or higher is the only stated prerequisite.
What is OpenFront.io?
It is a browser-based real-time strategy game focused on territorial control and alliance building, and a fork and rewrite of WarFront.io written primarily in TypeScript. The repository contains the client, a deterministic game simulation and the server.
What is an alternative to OpenFront.io?
The README credits WarFront.io at github.com/WarFrontIO as the project this forked from and rewrote. The README does not enumerate what changed between the two, so the repository itself will not settle the comparison.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openfrontio-openfrontio)