Framework
enable3d/enable3d avatar
enable3d/enable3d

enable3d: three.js physics and 3D objects packaged for Phaser and plain web apps

🕹️ Standalone 3D Framework / Physics for three.js (using ammo.js) / 3D extension for Phaser 3

1,180 stars101 forksJavaScriptLGPL-3.0

At a glance

What is it?
enable3d is a TypeScript monorepo of npm packages that wraps three.js and ammo.js into a 3D framework and a Phaser 3 extension, with a separately publishable ammo.js build for Node.js servers. The judgement is that the package split is the project's real contribution, and that the dependency list, which includes a 2D physics engine, is a fair warning about what gets pulled in.
Who is it for?
enable3d fits a browser game developer who has a Phaser 3 project or a plain three.js scene and wants physics and 3D objects without writing the ammo.js integration by hand, and who is prepared to work with the package boundaries the project defines.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 53 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Seven packages, and the diagram that explains them

enable3d is written in TypeScript and sits on top of three.js and ammo.js. The stated aim is to bring physics to a three.js project and the third dimension to a Phaser 3 game, and the project positions itself for web, mobile and PC.

What it does not do is ship as one library. The project is split into many separate npm packages, and the documentation points at a diagram explaining the structure and the relationships between them. The seven published packages each have a distinct job.

`enable3d` is the standalone 3D framework on top of three.js, and it is the entry point for a plain web project. `@enable3d/phaser-extension` integrates the three.js package into a Phaser 3 game. `@enable3d/ammo-physics` is the core physics package, wrapping ammo.js. `@enable3d/ammo-on-nodejs` enables running ammo.js on a Node.js server. `@enable3d/three-graphics` is the core 3D objects package, described as a readable API over many three.js elements. `@enable3d/three-wrapper` wraps the three.js library and some of its examples in one package. And `@enable3d/common` holds code used by almost every other package.

That structure is the project's main design decision and it is a sensible one. `three-graphics` on its own is useful to somebody who wants nicer three.js objects but no physics, `ammo-physics` is useful to somebody who wants physics but already has a scene graph, and `phaser-extension` is the bridge for a 2D engine that needs a 3D layer.

The `common` package is the one to be aware of as a user, because it means the packages are not independently versioned in practice: pulling in the physics package also pulls in the common one, and the two have to agree.

The dependency list tells you what you are signing up for

The declared dependencies are listed explicitly in the README, which is helpful because this is a project that reaches into the middle of your bundle.

json
{
  "@types/matter-js": "0.17.6",
  "@types/three": "0.171.0",
  "matter-js": "0.17.1",
  "phaser": "^3.55.2",
  "poly-decomp": "^0.3.0",
  "three": "0.171.0",
  "three-csg-ts": "^3.1.10"
}

The three.js and Phaser entries are the expected ones. Three is pinned exactly at 0.171.0 and the matching type package is pinned too, and the badge in the README tracks three r171. Phaser is a caret range at `^3.55.2`, and the README notes in parentheses that it also works on the latest Phaser versions such as 3.60 and 3.70.

The two entries that deserve a second look are `matter-js` and `poly-decomp`. matter-js is a 2D physics engine, and it is not obvious from the name enable3d that a 2D physics engine would be a dependency of a 3D framework. poly-decomp is the convex polygon decomposition library, and that one does make sense: physics bodies built from arbitrary concave shapes need to be split into convex pieces before a physics engine can handle them, and three-csg-ts in the list is a constructive solid geometry library, which is a related kind of geometry work.

So the geometry tooling is coherent. The matter-js dependency is the one to trace before adopting, because if your project already ships a different version of a 2D physics engine you may end up with two.

The version pinning is exact rather than ranged for the type packages and for three itself, which means an upgrade of three.js in your own project will not be picked up automatically and may need a matching release of enable3d.

The monorepo runs seven TypeScript watch processes at once

The root `package.json` is a workspace root, marked private with version `1.0.0`, and the workspaces are declared as `packages/*`. The build and development scripts show how the pieces fit together.

The development command is the interesting one. `npm run dev` runs `npm-run-all --parallel start:*`, which fans out to one `tsc --watch` process per package, each one scoped to its own directory. There are seven of them, for `common`, `threeWrapper`, `ammoPhysics`, `ammoOnNodejs`, `threeGraphics`, `phaserExtension` and `enable3d`, plus a `start:dev` that starts the `packages/dev` application.

That per-package watch is not arbitrary. Each published package is compiled on its own with `tsc`, and each has its own `publish:*` script that runs `npm publish` in that package directory. So the watch mode is watching the build output that the published artifacts are made from, and a change in `common` recompiles everything that depends on it, which is the point of watching it in parallel rather than in sequence.

The rest of the scripts are conventional. `build` runs `node scripts/build.mjs`, `bundle` runs the webpack and esbuild scripts in sequence, `format` is `prettier --write packages/**/*.ts`, and `lint` is `eslint packages/**/*.ts`. Publishing runs `clean:dist` first, then `tsc`, then the parallel publish tasks, and `lerna-version` handles the version bump across the packages with a build and bundle afterwards.

The cleanup scripts use `npx rimraf` to remove `packages/**/dist` and `bundles`, and there is a `prune` script backed by `scripts/prune.mjs` with a `prune.md` file documenting it, plus `prune.ps1` for PowerShell. The presence of a pruning step, a bundling step and a `bundlesTest/` directory tells you the project cares about what actually lands in a published tarball, which is a common source of pain in a package-per-feature monorepo.

ammo.js on the server, in the browser, and through Phaser

The three integration paths share a physics core but differ in how ammo.js is obtained, and the `@enable3d/ammo-on-nodejs` package exists to run ammo.js on a Node.js server.

The standalone path is the `enable3d` package, which gives you a 3D framework on top of three.js, with `@enable3d/three-graphics` providing the object API and `@enable3d/ammo-physics` providing the physics. This is the path for a plain three.js scene that wants rigid bodies and collision handling.

The Phaser path is `@enable3d/phaser-extension`, which integrates the three.js package into a Phaser 3 game. This is the one to reach for if you already have a 2D game and want 3D objects in it, for example a 2D platformer with a 3D item or a 2D scene with 3D overlays. The `phaser` dependency being a direct dependency of the project rather than a peer dependency is worth noting, since it means the Phaser version in your application and the one enable3d was built against are the same tree.

The Node path is the interesting one for server-authoritative games. `@enable3d/ammo-on-nodejs` enables running ammo.js on a Node.js server, which is what you need if you want to simulate physics on the server and send the results to clients. The `headless` script in the root package.json runs `nodemon packages/dev/src/headless-node.js`, which is the development entry point for that scenario.

The project also points at geckos.io for real-time multiplayer games, and links the geckos.io logo in the README, which suggests the server-side physics path is aimed at games with networked state.

There is a `WebXR.md` file at the repository root, so immersive web support is part of the scope, and the `webpack/` directory and `bundles/` and `bundlesTest/` directories at the root are where the bundled builds and their tests live.

Testing runs through jest and puppeteer, plus a dev server

The test setup is the part of the repository that shows how the project checks a 3D and physics stack, which is not trivial to test.

There are two jest configuration files at the root, `jest.config.cjs` and `jest-puppeteer.config.cjs`, and a `test/` directory. The puppeteer configuration is what makes browser-based testing possible, and the `bundlesTest/` directory alongside `bundles/` suggests the bundled artifacts are tested separately from the source packages.

The root `test` script is `npm-run-all test:*`, so any test script prefixed with `test:` in the workspace is run, which is the same fan-out pattern as the development script.

The development server deserves a note. The README suggests checking out Five Server instead of Live Server, and links both the npm package and a VS Code extension for it. For a project whose dev loop is a 3D scene served to a browser, choosing a static server that handles the right MIME types and reload behaviour is a real ergonomic decision, and the project has made it for you.

The `packages/dev` directory is the development application, with `start:dev` running `npm start` in it. The `readme/` directory holds the images used in the documentation, and the `scripts/` directory holds the build, bundle, prune and webpack and esbuild entry points.

Code style is enforced with prettier via a `.prettierrc` and eslint via `.eslintrc` with an `.eslintignore`, and there is a `.vscode/` directory and a `tsconfig.base.json` shared across the workspaces.

LGPL-3.0, a single author, and a lerna release flow

The licensing is worth reading precisely because of what it means for a game project.

Enable3d is licensed under LGPL-3.0, with copyright attributed to Yannick Deubel for 2022, and the README points at the `LICENSE` file for details. The LGPL is a copyleft licence, and for a library that a game links into, the practical question is whether your game has to be released under compatible terms. The LGPL is designed so that dynamic linking generally does not force the whole application to be relicensed, but the specific obligations depend on how you distribute and how you modified the library, and the `LICENSE` file is the text that decides the question. This is a licensing observation rather than legal advice.

The project is maintained by a single named author, who holds the copyright. There are also three separate community packages listed as useful, all under the `@yandeu` scope: `audio` for the Web Audio API, `keyboard` for keyboard event handling, and `tap` for mouse, touch and pointer interactions. That is a coherent set of the small pieces a browser game needs, and keeping them in the same scope means they share an author and a release rhythm.

The release machinery is lerna. The root `lerna.json` sits alongside the workspace configuration, and the `lerna-version` script runs `lerna version` with commit hooks and git tagging disabled, then rebuilds and rebundles. The `scripts/` directory and the `getChanges.sh` file at the root handle the change log and release steps.

The repository is not archived and the last push was on 2026-08-31. There are no GitHub releases, which is normal for a project published as many npm packages rather than as a single tagged artifact.

Editorial conclusion

enable3d fits a browser game developer who has a Phaser 3 project or a plain three.js scene and wants physics and 3D objects without writing the ammo.js integration by hand, and who is prepared to work with the package boundaries the project defines. It does not fit a project that wants a single dependency, since the work is spread across seven packages, and it does not fit a server-side simulation that has to run ammo.js in Node, where the separate `@enable3d/ammo-on-nodejs` package is the path and the browser-oriented packages are not. Verify first that the versions of `three` and `phaser` in your project fall inside the ranges the package declares, that the extra `matter-js` and `poly-decomp` dependencies do not conflict with what you already ship, and that the package you actually need is one of the seven published ones rather than the private monorepo root, since the root `package.json` is marked private and versioned `1.0.0` for the workspace rather than for distribution.

Frequently asked questions

What packages does enable3d publish on npm?

Seven: `enable3d` as a standalone 3D framework, `@enable3d/phaser-extension` for Phaser 3, `@enable3d/ammo-physics` wrapping ammo.js, `@enable3d/ammo-on-nodejs` for running ammo.js on a Node.js server, `@enable3d/three-graphics`, `@enable3d/three-wrapper` and `@enable3d/common`.

Which three.js and Phaser versions does enable3d support?

The declared dependencies pin `three` at 0.171.0 with matching types, and require `phaser` at `^3.55.2`, with the README adding that it also works on the latest Phaser versions such as 3.60 and 3.70.

Can enable3d run ammo.js physics on a Node.js server?

Yes, through the `@enable3d/ammo-on-nodejs` package, which exists to run ammo.js outside the browser. The root package.json has a `headless` script running `packages/dev/src/headless-node.js` under nodemon for that development loop.

How do I build and publish the enable3d packages?

The root scripts build with `node scripts/build.mjs`, bundle with webpack and esbuild, and the publish script runs `clean:dist`, then `tsc`, then the per-package `publish:*` tasks. Versioning across packages is handled by `lerna version` through the `lerna-version` script.

What licence is enable3d released under?

LGPL-3.0, with copyright attributed to Yannick Deubel for 2022. The `LICENSE` file at the repository root holds the full text, and the README links to it for details.

Official sources

  1. enable3d/enable3d on GitHub
  2. Issues
  3. License: LGPL-3.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/enable3d-enable3d.svg)](https://hysenlabs.com/projects/enable3d-enable3d)

Was this useful?