ECS engine,
built for performance.
A JavaScript ECS engine with a zero-allocation core, and a GPU-driven WebGPU renderer built into it. Runs a million entities without GC stutter. No editor-first workflow, no scene files - just code.
npm install @woosh/meep-engine The renderer is part of the engine.
Meep draws with Shade, the WebGPU renderer we built as a product of its own. It is a GPU-driven architecture rather than a scene-graph backend, and it is the reason the engine can put hundreds of thousands of individually-posed objects in front of you without instancing tricks.
- GPU-driven, visibility-buffer deferred. Meshlet-clustered geometry lives GPU-resident in one buffer, culling runs on the GPU, and the rasterizer writes a visibility buffer and a G-buffer instead of shading as it draws.
- WebGPU only. No WebGL fallback and no degradation tiers: hardware below the floor gets a clear message rather than a worse picture.
- In the frame. Virtual geometry and virtual textures, brick4 volumetric GI, ReSTIR direct lighting, GPU animation and skinning, TAA/NSS upscaling with dynamic resolution, and a GPU path tracer.
- Your own passes are first-class. Render extensions declare a phase and an order and exchange typed records with the frame, instead of patching the pipeline.
Most web engines are heavy, opinionated, and stutter.
Meep is built around a different premise: that web games can rival native code if you take memory layout, cache locality, and bundle size seriously. Every decision in the engine bends toward that goal.
Zero-garbage architecture
no GC spikesPay for what you import
~6,000 modulesCode-first
no editor-first workflowShade: the renderer
GPU-driven, WebGPUHierarchy: solved
parent-child transformsAI & simulation toolkit
rare in JSBattle-hardened
decade in productionInvisible at runtime.
In development, Meep runs with thousands of assertions to catch errors at the source. For production, a single Rollup plugin strips every assertion away. What ships is small, tight, and runs at the speed of light.
- ✓ Tree-shakes to only the modules you reference
- ✓ Zero runtime overhead from assertions
- ✓ Three dependencies in total - the renderer is part of the engine, not a peer
import { defineConfig } from "vite";
import strip from "@rollup/plugin-strip";
export default defineConfig({
plugins: [
{ ...strip({ functions: ["assert.*"] }), apply: "build" }
]
});Read the source. Build something.
Free for hobby and small commercial work. One-time, per-project pricing for everyone else - including studios. No seats, no annual contracts.