How to save and load a World
This guide shows a complete save/load flow:
register snapshot codecs
create a snapshot
persist to JSON
restore later
1) Define data components/resources
1
2
3
4
5
6
7
8
9
10
11
12
13
14 class Position {
constructor ( public x = 0 , public y = 0 ) {}
}
class Health {
constructor ( public hp = 100 ) {}
}
class GameState {
constructor ( public wave = 1 , public score = 0 ) {}
}
type SpawnConfig = { interval : number };
const SpawnConfigToken = (() => ({ interval : 1.0 })) as ComponentCtor < SpawnConfig > ;
2) Register snapshot codecs once at boot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import { SnapshotCodec , World , type ComponentCtor } from "archetype-ecs-lib" ;
const world = new World ();
const positionCodec : SnapshotCodec < Position , { x : number ; y : number } > = {
key : "comp.position" ,
serialize : ( v ) => ({ x : v.x , y : v.y }),
deserialize : ( d ) => new Position ( d . x , d . y ),
};
const healthCodec : SnapshotCodec < Health , { hp : number } > = {
key : "comp.health" ,
serialize : ( v ) => ({ hp : v.hp }),
deserialize : ( d ) => new Health ( d . hp ),
};
const gameStateCodec : SnapshotCodec < GameState , { wave : number ; score : number } > = {
key : "res.game-state" ,
serialize : ( v ) => ({ wave : v.wave , score : v.score }),
deserialize : ( d ) => new GameState ( d . wave , d . score ),
};
const spawnConfigCodec : SnapshotCodec < SpawnConfig , { interval : number } > = {
key : "res.spawn-config" ,
serialize : ( v ) => ({ interval : v.interval }),
deserialize : ( d ) => ({ interval : d.interval }),
};
world . registerComponentSnapshot ( Position , positionCodec );
world . registerComponentSnapshot ( Health , healthCodec );
world . registerResourceSnapshot ( GameState , gameStateCodec );
world . registerResourceSnapshot ( SpawnConfigToken , spawnConfigCodec );
Only registered types are persisted.
3) Create a snapshot and persist it
const snapshot = world . snapshot ();
const json = JSON . stringify ( snapshot );
localStorage . setItem ( "save-slot-1" , json );
4) Restore from persisted JSON
const raw = localStorage . getItem ( "save-slot-1" );
if ( raw ) {
const snapshot = JSON . parse ( raw );
world . restore ( snapshot );
}
restore() will clear runtime queues (pending commands/events) and reconstruct persisted entity/resource state.
5) Common pattern: baseline + quick save
1
2
3
4
5
6
7
8
9
10
11
12
13
14 const baseline = world . snapshot (); // after bootstrap
let quickSave : ReturnType < World [ "snapshot" ] > | null = null ;
function doQuickSave () {
quickSave = world . snapshot ();
}
function doQuickLoad () {
if ( quickSave ) world . restore ( quickSave );
}
function resetRun () {
world . restore ( baseline );
}
6) Important checks
Register codecs before calling restore(...).
Keep codec keys stable across versions.
Ensure codec output is JSON-safe if you store saves as JSON.
Re-register systems/schedules in app boot code (they are runtime behavior, not snapshot data).
February 8, 2026
February 8, 2026