The application framework for Three.js games — one codebase, web and native.
Write ordinary three/webgpu. Ship it to the browser, desktop, Android, and iOS.
Quickstart · Templates · Packages · Docs · Contributing
ThreeNative does not replace Three.js — it is Three.js, with the game layer and the platform
layer filled in. ctx.scene is a THREE.Scene, ctx.renderer is a WebGPURenderer, and every
Three.js tutorial from the last decade still applies inside a ThreeNative scene.
| Plain Three.js | ThreeNative | |
|---|---|---|
| Rendering |
three/webgpu, TSL, your materials |
The same three/webgpu, unchanged and unwrapped |
| Game loop, fixed timestep, dt clamp | You write it, in every project | Shipped |
| Input | Per-project key, pointer, pad and touch plumbing | One input map; ctx.input.vector("move") on every device |
| Physics and navigation | Pick a library, write the bridge |
RigidBody3D, Area3D, CharacterBody3D over Rapier |
| HUD and menus | Hand-rolled DOM, or a second render loop | React 19 + Tailwind bound to game state at ~10 Hz |
| Assets | Manual copies and paths |
assets/ in, hashed output and a manifest out |
| Proof it still works | Screenshots and hope | Playtest scenarios that drive a real build and assert |
| Desktop, Android, iOS | Browser only | An owned C++ runtime running the same source |
| The look | Yours | Yours — visual code is generated into src/render/, never hidden in a package |
The framework owns the wiring and never the look. Anything that decides how a frame looks — materials, lighting, tonemapping, post, camera framing — is scaffolded into your repo as ordinary Three.js you can read, edit, or delete.
pnpm create threenative my-game
cd my-game
pnpm install
pnpm devThat is a complete game: a loop, physics, a React HUD, a playtest scenario, and a scene you can edit. Requires Node 20.19+ and a WebGPU-capable browser (WebGL2 fallback is automatic).
The real portable entry from the minimal template's src/game.ts:
import { defineGame } from "@threenative/core";
import { playtest } from "@threenative/core/playtest";
import type { IPhysicsContext } from "@threenative/physics";
import { rapier } from "@threenative/physics";
import config from "../threenative.config.js";
import { Play } from "./scenes/Play.js";
import type { GameState } from "./state.js";
const game = defineGame<GameState, IPhysicsContext>({
input: {
move: {
down: ["ArrowDown", "KeyS"],
left: ["ArrowLeft", "KeyA"],
right: ["ArrowRight", "KeyD"],
up: ["ArrowUp", "KeyW"],
},
},
plugins: [rapier(), playtest()],
render: config.renderer,
scenes: { play: Play },
start: "play",
});
export default game;A scene is a class with three optional methods — load, enter, update. That is the whole
lifecycle.
-
Godot-shaped conventions.
RigidBody3D,CharacterBody3D,Area3D,CollisionShape3D— borrowed vocabulary, so there is nothing new to learn. - Conventions on by default. Feet meet the floor, a weapon stays in the hand that holds it, an agent walks around a wall, one metre is one metre — each with a named override on the same object.
- React HUD bindings. Game state flows into React through an external store that never re-renders on the game loop.
- A real test harness. Playtest scenarios drive the actual build in a browser or on a device and assert what happened — frames, transforms, state, performance.
- An asset pipeline. Models and textures compile to hashed, manifest-tracked output.
- An owned native runtime. The same TypeScript runs on a C++ host for desktop, Android and iOS.
- Built for agents. A searchable capability manifest ships with the library and is exposed over MCP, so an authoring agent finds what already exists instead of rewriting it.
pnpm create threenative my-game --template <name>
| Template | What you start with |
|---|---|
starter (default)
|
A polished default project with a React HUD, physics, and a ready-to-edit scene |
minimal |
The smallest project — core and physics only |
platformer |
Jumping, patrols, pickups, camera follow |
action-rpg |
A three-room dungeon with melee, loot, equipment, and persistence |
defense |
Tower placement, routes, waves, and income |
racing |
Three laps, checklines, rescue sectors, boost pads |
sailing |
Wind, waves, buoyancy, and an ordered course |
shooter |
Hitscan and projectile weapons, hunting targets, timed pickups |
Details in create-threenative.
| Package | Purpose |
|---|---|
@threenative/assets |
Build-time asset compile step: assets/ in, hashed outputs and a manifest out |
@threenative/core |
Bootstrap, scenes, lifecycle, input, and renderer integration |
create-threenative |
Scaffold a readable game project from eight templates |
@threenative/physics |
Rapier-backed Godot-shaped physics and navigation |
@threenative/playtest |
Browser, native, and scenario assertion harness |
@threenative/runtime-native |
Owned C++ host for desktop, Android, and iOS |
@threenative/raw-unreal |
Raw Unreal editor .uasset static-mesh loader — UE5 FMeshDescription and UE4.18 FRawMesh, no interchange conversion |
@threenative/ui |
React bindings for HUD and game state |
@threenative/ueformat |
UEFormat v10 .uemodel parser and Three.js loader for meshes exported from Unreal packages |
threenative-engine-mcp |
Offline MCP capability discovery for authoring agents |
threenative-blender-mcp |
Drives an installed Blender headlessly so a downloaded .fbx becomes a loadable GLB — ships no Blender |
ThreeNative is alpha: the API is settling and versions are 0.x.
| Platform | Renderer | State |
|---|---|---|
| Web | WebGPU, WebGL2 fallback | Verified every CI run |
| Desktop (Linux, macOS, Windows) | Owned native host | Verified — 300 native frames and a non-blank capture |
| Android | Owned native host | Emulator lane runs; physical-device performance is being measured |
| iOS | Owned native host | Simulator evidence produced on a hosted macOS runner |
Every claim here is backed by a run. The current numbers live in
docs/verification/runtime-perf-state.md, and
everything the framework does not yet do well — with what is being done about it — is in one
place: docs/CURRENT-CHALLENGES.md.
The marketing site lives in site/ as a private workspace app — never a published package. It is
prerendered to static HTML at build time and hydrated on the client, so every headline, feature and
code sample is in the source a crawler downloads.
pnpm site:dev # vite dev server
pnpm site:build # client bundle, SSR bundle, prerendered HTML, sitemap
pnpm site:deploy # wrangler, Cloudflare static assetsIts claims are typed data with evidence pointers, and its code samples are real files compiled against the shipped packages, so renaming an export breaks the site build rather than the site.
-
docs/README.md— the map: PRDs, verification, benchmarks, strategy, architecture, product, spikes. -
docs/architecture/CHARTER.md— what the framework is, what it refuses to be, and the rules that decide both. Binding. -
docs/architecture/AGENT-INTERFACE.md— the surface an authoring agent reads. -
packages/create-threenative/README.md— templates and the scaffold command.
Contributions are welcome — issues, discussions and pull requests alike.
pnpm install --frozen-lockfile
pnpm typecheck && pnpm lint && pnpm testNative compilation is opt-in; the default gate needs no CMake, NDK, or Xcode. There is no root
pnpm dev — run an example by name, for example pnpm --filter abyss-framework dev.
Read CONTRIBUTING.md before opening a pull request, and
AGENTS.md for the full working conventions. Everyone taking part is expected to
follow the Code of Conduct.
- Questions and ideas → GitHub Discussions
- Bugs and feature requests → Issues
-
Security reports →
SECURITY.md(please do not open a public issue)
MIT — see LICENSE. ThreeNative is MIT end to end, including the native runtime.