Getting Started
Build your first web game.
This guide walks you through installing the CLI, scaffolding a project, writing game logic with the ECS architecture, and shipping to production - all in one place.
Prerequisites
NanoForge requires Node.js 25+ and a package manager. We recommend pnpm, but npm, yarn, and bun all work.
Node.js
≥ 25
LTS recommended
Package manager
pnpm / npm / yarn / bun
your choice
TypeScript
optional
highly recommended
Install the NanoForge CLI globally:
Create a project with editor support
Pass --editor to nf new to scaffold
a project that includes the editor entry points and save file at
.nanoforge/.
The --editor flag adds editor-specific dependencies and generates
the .nanoforge/editor/ entry points alongside your regular
client/ source.
Start the editor
Run nf editor from inside your project directory. The editor is a
web app that opens at http://localhost:4000.
Load your project
The editor opens on the project loader page. You have two options:
Create new project
Opens a form asking for a project name and local path. The editor initialises a fresh save file.
Open project
Load a project already present on disk. The editor reads the save file and regenerates the editor entry point.
Recent projects are cached in the browser so you can reopen them with a single click.
Create and edit entities
Inside the workspace, use the scene hierarchy to spawn entities and the component inspector to attach data.
- 1
In the hierarchy panel, click + New entity and choose a name. A blank entity appears.
- 2
Select the entity. In the inspector on the right, click Add component and pick
Position. Setx: 400,y: 300. - 3
Add a second component:
Velocity. Setvx: 120,vy: 0. - 4
The editor writes automaticaly modifications in
.nanoforge/client.save.json.
// .nanoforge/client.save.json - written by the editor on File › Save { "entities": [ { "id": "entity_42", "components": [ { "type": "Position", "x": 400, "y": 300 }, { "type": "Velocity", "vx": 120, "vy": 0 } ] } ] }
Generate & run
Then let's build and start the game. nf dev generate the entry point,
builds and serves the client - the game reflects your latest editor changes:
Run editor
nf editor . - the editor UI
Run project in dev mode
nf dev --generate --editor - generate, build and serves the game
Deploy with project manager
When you're ready to share your game, push it to GitHub and connect it to the Project Manager. It handles builds, versioning, and hosting so your players always get the latest version.
Push to GitHub
Commit your project and push it to a GitHub repository. The Project Manager reads directly from your repo.
Create a project
In the Project Manager, create a new project and link it to your GitHub repository.
Build
Trigger a build from the Project Manager dashboard. It pulls your latest commit, installs dependencies, and compiles the game.
Deploy
Once the build succeeds, deploy with one click. Your game is live at a shareable URL — no install required.
NanoForge games are served as a URL — no client install, no plugins. Your players open a link and the game runs.
Prerequisites
NanoForge requires Node.js 25+ and a package manager. We recommend pnpm, but npm, yarn, and bun all work.
Node.js
≥ 25
LTS recommended
Package manager
pnpm / npm / yarn / bun
your choice
TypeScript
optional
highly recommended
Install the NanoForge CLI globally:
Create a project
Run nf new to scaffold a new project. The interactive wizard will
ask you a few questions about your setup.
You can also pass flags to skip the wizard:
Project structure
nf new generates the following layout. All your game logic lives
in client/ (browser) and optionally
server/ (for multiplayer).
my-game/ ├── client/ # browser-side entry point │ └── main.ts ├── server/ # node.js server (multiplayer) │ └── main.ts ├── nanoforge.config.json # build & runtime config ├── package.json └── tsconfig.json
The generated client/main.ts exports a main()
function that NanoForge calls to boot your game:
import { type IRunOptions } from '@nanoforge-dev/common'; import { NanoforgeFactory } from '@nanoforge-dev/core'; export async function main(options: IRunOptions) { const app = NanoforgeFactory.createClient(); // register libraries, then init and run await app.init(options); await app.run(); }
Core concepts
NanoForge uses an Entity-Component-System (ECS) architecture. Everything in your game — players, projectiles, tiles — is an entity made of components, processed by systems.
Entity
A unique ID in the world. Has no data of its own — it is the sum of its components.
player, bullet, tile
Component
Plain data attached to an entity. A Position, a Velocity, a Health value.
Position, Velocity, Health
System
A function that runs every tick, queries entities with specific components, and transforms them.
moveSystem, drawSystem
Systems never know about each other. They only query the components they care about. This makes it easy to add, remove, or replace behaviour without touching unrelated code.
First game logic
Let's build a moving square. First, define two components to describe an entity's position and velocity:
export class Position { constructor( public x: number, public y: number, ) {} } export class Velocity { constructor( public vx: number = 0, public vy: number = 0, ) {} }
Then write a system that reads those components and moves entities each tick. The getZipper call returns only entities that have all the listed
components:
import type { Registry, Context } from '@nanoforge-dev/ecs-client'; import { Position, Velocity } from '../components'; export function moveSystem(registry: Registry, ctx: Context) { const entities = registry.getZipper([Position, Velocity]); for (const entity of entities) { entity.Position.x += entity.Velocity.vx * ctx.deltaTime; entity.Position.y += entity.Velocity.vy * ctx.deltaTime; } }
Register the ECS library, then spawn an entity and attach components in your main() function. The registry is the entry point for all entity and system
management:
import { ECSClientLibrary } from '@nanoforge-dev/ecs-client'; // ... other imports export async function main(options: IRunOptions) { const app = NanoforgeFactory.createClient(); const ecs = new ECSClientLibrary(); app.useComponentSystem(ecs); await app.init(options); const registry = ecs.registry; const player = registry.spawnEntity(); registry.addComponent(player, new Position(400, 300)); registry.addComponent(player, new Velocity(120, 0)); registry.addSystem(moveSystem); await app.run(); }
To render the entity, add a draw system using the @nanoforge-dev/graphics-2d library:
import { Graphics2DLibrary, Rect } from '@nanoforge-dev/graphics-2d'; import type { Registry, Context } from '@nanoforge-dev/ecs-client'; import { Position } from '../components'; export function drawSystem(registry: Registry, ctx: Context) { const graphics = ctx.libs.getGraphics<Graphics2DLibrary>(); const entities = registry.getZipper([Position]); for (const entity of entities) { const rect = new Rect({ x: entity.Position.x, y: entity.Position.y, width: 32, height: 32, fill: '#7c3aed', }); graphics.stage.add(rect); } }
Run in dev mode
nf dev compiles your project, starts both client and server, and
watches for changes with hot reload.
Hot reload
Save a file and the engine recompiles and reloads without losing entity state.
Dev tools
Inspect entities and tweak components live with the built-in visual editor.
Install packages
The NanoForge Registry hosts ready-to-use components, systems, and templates. Install them with nf install:
Once installed, packages are imported like any TypeScript module. The CLI also generates stubs for components and systems so you can start using them immediately.
Build & deploy
When you're ready to ship, build your project and start the production server:
You can also manage deployments directly from the Project Manager — a web dashboard where you can monitor builds, manage multiple projects, and invite collaborators.
NanoForge games are served as a URL — no client install, no plugins. Your players open a link and the game runs.