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
Shade

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.

Coming from 2.x? Read the migration guide →

Why Meep

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.

Pure ECS

data-oriented
A true Entity-Component-System foundation - not an OOP engine with ECS bolted on. One component per type per entity. Memory layout is predictable. Component queries are instantaneous, even with millions of entities.

Zero-garbage architecture

no GC spikes
Custom memory management eliminates the per-frame allocation pattern that destroys frame consistency on the web. Meep handles millions of objects on low-spec mobile without GC pauses.

Pay for what you import

~6,000 modules
The engine ships as ~6,000 fine-grained ES modules that tree-shake to only what you reference: import a lerp function and pay for a lerp function. A build that never draws carries none of the renderer, and one that does starts streaming assets as soon as the device is up, rather than after a monolithic runtime has unpacked itself.

Code-first

no editor-first workflow
No proprietary file formats, no project the editor owns. Meep is built for engineers who treat their codebase as the source of truth - and when you do want to look inside a running game, an in-app editor attaches to it with one call and detaches again.

Shade: the renderer

GPU-driven, WebGPU
Meep draws with Shade, its own renderer. Geometry is clustered into meshlets and lives GPU-resident; culling runs on the GPU; the rasterizer writes a visibility buffer and a G-buffer instead of shading as it draws, and thousands of lights are binned into froxels and applied deferred. Virtual geometry, virtual textures, volumetric GI, GPU skinning and a GPU path tracer come with it.

Hierarchy: solved

parent-child transforms
Pure ECS engines historically struggle with scene graphs. Meep gives you the composability of a hierarchy with the raw speed of a flat array - without compromising either side.

AI & simulation toolkit

rare in JS
Behavior trees, blackboards, Monte-Carlo Tree Search (AlphaGo's algorithm), resource allocation solvers, FABRIK IK, BVH spatial queries. Industrial decision-making tools.

Battle-hardened

decade in production
Powers Might is Right on Steam. ~15,000 handwritten tests cover critical algorithms, edge cases and determinism. 6,000+ assertions in dev mode catch errors instantly; stripped from production builds.
Production builds

Invisible 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

Read the install guide →

vite.config.js
import { defineConfig } from "vite";
import strip from "@rollup/plugin-strip";

export default defineConfig({
  plugins: [
    { ...strip({ functions: ["assert.*"] }), apply: "build" }
  ]
});
Get started

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.