Entity Component System
Archetype-based ECS with SoA columnar storage, typed queries, dependency-based scheduling, and parallel Web Worker execution.
A composable TypeScript engine ecosystem with 92+ packages. Use what you need, swap what you want.
Use the engine meta-package for the full stack, or pick individual packages for exactly what you need.
import {
create2DEngine,
defineComponent,
defineSystem,
queryBuilder,
CoreSchedule,
} from '@web-engine-dev/engine';
// Define components
const Position = defineComponent('Position', { x: 'f32', y: 'f32' });
const Velocity = defineComponent('Velocity', { x: 'f32', y: 'f32' });
// Define a query and system
const movables = queryBuilder().with(Position, Velocity).build();
const moveSystem = defineSystem({
name: 'Move',
fn: (world) => {
for (const { entity, components: [pos, vel] } of world.run(movables)) {
pos.x += vel.x;
pos.y += vel.y;
world.insert(entity, Position, pos);
}
},
});
// Create engine with 2D preset (60 FPS, fixed timestep, physics-ready)
const engine = create2DEngine(undefined, {
onInit(engine) {
engine.scheduler.addSystem(CoreSchedule.Update, moveSystem);
const player = engine.world.spawn();
engine.world.insert(player, Position, { x: 0, y: 0 });
engine.world.insert(player, Velocity, { x: 1, y: 0.5 });
},
});
await engine.start(); // Game loop runs automaticallyimport { defineComponent, createWorld, queryBuilder } from '@web-engine-dev/ecs';
const Position = defineComponent('Position', { x: 'f32', y: 'f32' });
const Velocity = defineComponent('Velocity', { x: 'f32', y: 'f32' });
const world = createWorld();
const entity = world.spawn();
world.insert(entity, Position, { x: 0, y: 0 });
world.insert(entity, Velocity, { x: 1, y: 2 });
const movables = queryBuilder().with(Position, Velocity).build();
for (const { entity, components: [pos, vel] } of world.run(movables)) {
pos.x += vel.x;
pos.y += vel.y;
world.insert(entity, Position, pos); // Write changes back
}import { Vec3, Mat4, Quat } from '@web-engine-dev/math';
const position = Vec3.create(1, 2, 3);
const rotation = Quat.fromEuler(0, Math.PI / 4, 0);
const transform = Mat4.fromRotationTranslation(rotation, position);
const forward = Vec3.transformMat4(Vec3.FORWARD, transform);Use what you need. Every package works independently. Need just math and ECS? Install two packages. Need a full 3D game engine with physics, audio, and networking? Install the umbrella package. No monolithic downloads, no unused code.
Swap what you want. Interface-first design means you can swap subsystems without changing gameplay code. Move from the built-in physics to Rapier WASM by changing one import.
TypeScript to the core. Not a JavaScript engine with type definitions bolted on. Built from scratch with strict TypeScript, branded types, and discriminated unions. Invalid states are compile errors, not runtime crashes.
Data-oriented performance. The ECS uses archetype-based SoA columnar storage for cache-friendly iteration. Zero-allocation hot paths, object pooling, and batch math operations on typed arrays. GPU-driven rendering with instanced draw calls.
| Category | Count | Highlights |
|---|---|---|
| Core | 12 | math, ecs, events, time, scheduler, serialization, reflection, scripting, splines |
| Rendering | 12 | renderer, render-graph, shader-compiler, gltf, particles, sprites, terrain, gizmos |
| Systems | 17 | input, audio, physics2d/3d, animation, netcode, character, cloth, ragdoll |
| Gameplay | 5 | ai (behavior trees, GOAP, utility), pathfinding (A*, JPS, HPA*, flow fields, NavMesh), procgen |
| Infrastructure | 16 | assets, scene, prefab, save, build, debug, storage, streaming, compression |
| Meta | 14 | engine, editor-core, editor-ui, camera, tween, timer, signals, devtools |
| Player | 4 | i18n, achievements, accessibility, telemetry |
| Platform | 9 | analytics, social, monetization, ugc, publishing, sandbox |
| Runtime | 3 | mobile, pwa, xr |
| Games | 1 | space-shooter (reference game) |