Easy to Use
Straightforward API for defining components, creating entities, and writing systems. Full type-safety with TypeScript.
Easy to Use
Straightforward API for defining components, creating entities, and writing systems. Full type-safety with TypeScript.
Reactive Queries
Track all changes to entities and components automatically. Query for entities that were added, removed, or changed since the last frame.
Built-in Multithreading
Run heavy workloads in parallel without any jank. Effortlessly distribute work across multiple CPU cores, no manual thread management required.
Open Source
Read the source code, create issues, and contribute on GitHub. We welcome contributions and feedback as the project grows.
import { addComponent, createEntity, defineComponent, defineQuery, defineSystem, removeEntity, field, World,} from '@woven-ecs/core';
// Define components with typed fieldsconst Particle = defineComponent({ position: field.tuple(field.float32(), 2), velocity: field.tuple(field.float32(), 2), color: field.tuple(field.uint8(), 4), // RGBA life: field.float32(),});
// Query all particlesconst particles = defineQuery((q) => q.with(Particle));
// Spawn a burst of particlesfunction emit(ctx, x, y, count) { for (let i = 0; i < count; i++) { const angle = Math.random() * Math.PI * 2; const speed = 50 + Math.random() * 100; const eid = createEntity(ctx); addComponent(ctx, eid, Particle, { position: [x, y], velocity: [Math.cos(angle) * speed, Math.sin(angle) * speed], color: [255, 140, 50, 255], life: 1.0, }); }}
// Update particles: move, fade, and destroy dead onesconst particleSystem = defineSystem((ctx) => { const dt = ctx.time.deltaMs / 1000; for (const eid of particles.current(ctx)) { const p = Particle.write(ctx, eid); p.position[0] += p.velocity[0] * dt; p.position[1] += p.velocity[1] * dt; p.life -= dt; if (p.life <= 0) removeEntity(ctx, eid); }});
// Create the world and runconst world = new World([Particle]);
// An initial burst of particlesworld.execute((ctx) => emit(ctx, 400, 300, 200));
function loop() { world.sync(); world.execute(particleSystem); requestAnimationFrame(loop);}
loop();with, without, and any operatorsThe @woven-ecs/canvas-store and @woven-ecs/canvas-store-server packages extend Woven-ECS with everything you need to build multiplayer editor applications like infinite canvases or other creative design tools.
Real-time Sync
WebSocket-based multiplayer with conflict resolution. Multiple users can edit the same document simultaneously.
Local-First
Your app works offline by default. Data lives on the client and syncs to the server when connected.
Undo/Redo
Full history tracking with configurable depth. Support for undo/redo across multiple users with proper conflict resolution.
Persistence
Automatic IndexedDB storage for offline support. Changes are saved locally and synced when back online.
Migrations
Version your component schemas with automatic migrations. Evolve your data model without breaking existing documents.
Configurable
Configure sync behavior per component: persist to server, sync ephemerally, store locally, or skip entirely.
Learn more about canvas-store →
Woven Canvas is an open-source infinite canvas SDK. It has a plugin architecture and is very customizable. If you’re building a collaborative whiteboard or design tool, give Woven Canvas a look!