API reference
Each JavaScript entry point ships ESM and CommonJS with matching declarations. Peers are optional in the manifest; applications install the peers their chosen entry point requires. The core has no dependencies. See Getting started for installation and complete host examples.
Core: game-mount
Pixel ratio
| Export | Contract |
|---|---|
DEFAULT_MAX_DPR | 2 |
readDevicePixelRatio() | Global positive finite ratio, otherwise 1 |
getDpr(maxDpr = 2, devicePixelRatio = readDevicePixelRatio()) | min(maxDpr, max(1, devicePixelRatio)); cap must be positive and finite or throws RangeError |
dprRange(maxDpr = 2) | Readonly [min(1, maxDpr), maxDpr]; same cap validation |
A cap below 1 deliberately permits undersampling. Pass a valid device ratio when supplying the second getDpr argument explicitly.
Quality and environment
RenderQuality has readonly maxDpr: number and antialias: boolean. QualityTier is "low" | "medium" | "high".
| Tier | maxDpr | antialias |
|---|---|---|
QUALITY_TIERS.low | 1 | false |
QUALITY_TIERS.medium | 1.5 | true |
QUALITY_TIERS.high | 2 | true |
DEFAULT_QUALITY is high. detectQualityTier(navigator?) returns low on mobile and high elsewhere; detectQuality(navigator?) returns its quality object.
isMobileDevice(navigator?) uses Client Hints, a mobile user agent or touch-capable iPadOS detection. NavigatorLike contains optional userAgent, maxTouchPoints and userAgentData.mobile. This is a rendering-budget heuristic; use viewport measurements for layout.
detectReduceMotion() reads prefers-reduced-motion: reduce, returning false when unavailable or the query throws. It does not disable animations itself.
Host and phase
GAME_CANVAS_HOST_CLASS is "game-canvas-host". gameCanvasHostStyle supplies the parent-sized flex host contract; GameCanvasHostStyle is its type. The identical CSS contract is exported from game-mount/styles.css. The parent must have a resolved height.
isActivePhase<T extends string | number>(current: T, match: T | readonly T[]): boolean matches one phase or several.
Adaptive-resolution ladder
stepPixelRatio(input: StepPixelRatioInput): StepPixelRatioResult is a pure state transition. Input fields are avgFps, current, cap, consecutiveLow and consecutiveHigh. Output fields are next, consecutiveLow and consecutiveHigh; feed the counters into the next call and apply next to the renderer.
- Two consecutive windows below
LADDER_LOW_FPS(30) step down. - Two above
LADDER_HIGH_FPS(55) step up. - Intermediate windows clear both counters.
LADDER_STEPis 0.1 andLADDER_FLOORis 0.5; upward steps stop atcap.
Provide valid finite samples and a current ratio within your intended bounds. The function performs transitions, not general input validation or normalization.
Asset errors
errorMessage(error: unknown): string extracts an Error message or stringifies the thrown value. classifyAssetError(error) returns { url, assetType }, with "unknown" when it cannot identify either. AssetErrorClass is "model" | "texture" | "wasm" | "font" | "audio" | "unknown".
AssetErrorReason adds a message: string to that classification. Detection uses the first absolute or root-relative URL and its extension; it is best-effort, not a security or network-status classifier.
React: game-mount/react
Requires React. GameCanvasErrorBoundary takes GameCanvasErrorBoundaryProps:
| Prop | Meaning |
|---|---|
children? | Canvas subtree |
onError | Required callback receiving AssetErrorReason |
fallback? | React node shown after failure; defaults to nothing |
Place a DOM fallback outside the renderer's internal scene tree. To retry, remount the boundary with a new key. Error URLs and messages should be displayed as text.
Pixi: game-mount/pixi
Requires PixiJS 8. mountPixi(options?: MountOptions): Promise<PixiMountHandle> resolves after Application initialization.
| Mount option | Default and behavior |
|---|---|
container? | Parent for an owned canvas |
canvas? | Omit for a fresh owned canvas; a supplied canvas stays in the DOM after destroy |
background? | Near-black clear color; number or string |
quality? | DEFAULT_QUALITY |
pixelSnap? | false; true forces resolution 1, no antialiasing and rounded pixels |
reduceMotion? | Detected preference |
resizeMode? | "observer"; also "resizeTo" or "manual" |
resizeTarget? | Container for an owned canvas, otherwise canvas |
onResize? | (width, height) => void, after the renderer resizes |
PixiMountHandle exposes readonly app, canvas, reduceMotion, width, height, plus resize(width, height) and idempotent destroy(). Sizes are integer CSS pixels, at least 1×1. Same-size requests are ignored. Destroy detaches wiring, destroys scene children while keeping shared textures, and removes only an owned canvas.
applyFilterResolutionFix() sets Pixi's default filter resolution to "inherit" for filters created afterward. Call explicitly before creating filters when needed; it changes the global Pixi default.
Pixi hook: game-mount/pixi/react
Requires React and PixiJS 8. usePixiMount(ref, options?: MountOptions): PixiMountHandle | null mounts into a referenced element and cleans up on unmount. Prefer an HTMLElement container ref, so StrictMode always gets a fresh canvas. A canvas ref is unsafe for remounts after destruction.
The handle is null until asynchronous initialization completes. Options are read when the mount effect runs; changing options does not remount. Change the component key to rebuild with new options.
@pixi/react: game-mount/pixi/pixi-react
Requires React, PixiJS 8 and @pixi/react 8. PixiReactMount wraps the Application owned by @pixi/react. It never creates another Application.
PixiReactMountProps includes children, className, background, quality, pixelSnap, reduceMotion, resizeMode, resizeTarget, onResize and onReady. Defaults match imperative Pixi. PixiReactResizeTarget accepts an HTMLElement, Window or HTMLElement ref; by default the parent sets the size.
onReady(handle) receives a PixiReactMountHandle with app, canvas, reduceMotion, width, height and resize(). It has no destroy() because React owns teardown. Mount options are captured for the component lifetime; change its key to rebuild. Callbacks use their latest props.
Use a browser bundler: @pixi/react 8.0.5's extensionless dependency import prevents plain Node ESM loading. The packed smoke resolves ESM and loads CommonJS; the real-WebGL browser test loads the actual component.
r3f: game-mount/r3f
Requires React, Three and @react-three/fiber 9. GameCanvas fills its parent with an inline host contract and an r3f Canvas. GameCanvasProps extends Canvas props except dpr and gl:
| Prop | Default and behavior |
|---|---|
active | Required; false unmounts the canvas |
children | Required scene children |
quality? | DEFAULT_QUALITY |
onContextLost?, onContextRestored? | Canvas callbacks; defaults log warnings |
preserveDrawingBuffer? | false; enable only for readback |
toneMappingExposure? | 1 |
hostProps? | Div attributes, merged class name and overriding styles; GameCanvasHostProps supports data-* |
The renderer uses ACES filmic tone mapping, sRGB output and high-performance power preference. Context loss calls preventDefault; restoration remounts the canvas. Keep persistent state outside scene children.
AdaptiveResolution takes AdaptiveResolutionProps: maxDpr = 2, startDpr = 1.5, priority = 0 and onUpdate?. Place it inside GameCanvas and pass the same quality cap. It samples 60-frame windows with a two-second settling period and drives the shared ladder.
onUpdate receives AdaptiveResolutionInfo: fps, pixelRatio, and optional peak drawCalls and triangles. A positive priority disables r3f automatic rendering; use it only when another component owns rendering manually. Prefer ESM because Three's CommonJS build emits a deprecation warning.
Babylon: game-mount/babylon
Requires React, Babylon core and Reactylon.
babylonEngineOptions(input?: BabylonEngineOptionsInput) returns EngineOptions. Input accepts quality?, navigator? and overrides?. Quality defaults to detected low on mobile, high elsewhere. Options cap the device ratio, enable adaptation, disable preserved drawing buffers, and select mobile low-power/no-stencil or desktop high-performance/stencil. Overrides are spread last and can replace policy values.
SceneRoot<T> takes SceneRootProps<T>: activeKey, matchKey (one key or a readonly list) and children(root: TransformNode). It creates a root while matched and disposes it and parented content on exit. Keep Engine and Scene mounted above it. Parent meshes to the supplied root.
useBeforeRender(callback, deps = []) registers a Reactylon scene observer and removes it on unmount. The callback receives (deltaSeconds, scene) with delta capped at MAX_FRAME_DELTA (0.05 seconds). The latest callback is used without resubscribing unless scene or dependencies change.
Havok: game-mount/babylon/havok
Requires React, Babylon core and Havok. useHavokPhysics(wasmBaseUrl = "/havok/"): UseHavokPhysicsResult returns { plugin: HavokPlugin | null, error: Error | null }.
Serve HavokPhysics.wasm yourself; custom base URLs need a trailing slash. Enable physics on the scene and choose gravity/units in application code once the plugin is available. Loads are cached by the current base URL; a failed load clears its cache for a later mount to retry. This entry registers Babylon's physics scene component on import.
_resetHavokPhysicsCache() clears the cache for tests. It is not an application lifecycle primitive.