Skip to content

React adapter roots

A React root is an entry in vgai.project.json.roots whose adapter is dom. It mounts as a DOM layer in the same z-ordered host stack as gameplay canvases:

A React adapter root flows from its JSX entry through the automatic WorldProvider into the z-ordered host stack
A React root uses the same declared composition and lifecycle as canvas roots; JSX remains its authored document.
vgai.project.json (excerpt)
{
"manifestVersion": 2,
"roots": [
{ "id": "main", "adapter": "three", "entry": "src/world.tsx" },
{ "id": "menu", "adapter": "dom", "entry": "src/menu.tsx", "zOrder": 10 }
]
}

The entry module default-exports a component. The host wraps it in the engine WorldProvider, so it can subscribe to live state without a local provider shim:

src/menu.tsx
import { useWorldState } from '@engine/react/world-state';
import { getHudState } from './game-state';
export default function Menu() {
const hud = useWorldState(() => getHudState());
return <button style={{ pointerEvents: 'auto' }}>HP: {hud.health}</button>;
}

A React root has no scene file. The editor derives its hierarchy from stable OID instrumentation in the served TSX, and inspector edits write back to JSX. React nodes do not host per-frame gameplay; behavior lives in gameplay roots and the React tree renders from shared game state.

The manifest composer mounts and disposes React with every other root. Layers are click-through by default; interactive elements opt in with pointer-events: auto.