ExoJS is a TypeScript-first 2D runtime for browser games and interactive apps. It is designed around explicit scene flow, practical rendering features, and predictable runtime behavior.
- TypeScript-first API surface with strong runtime contracts
- Scene and asset workflows built for real game loops
- Modern rendering stack: WebGPU-first with WebGL2 fallback
- Practical visuals: filters, masks, render passes, cache-as-bitmap
- Gameplay tools: animated sprites, scene stacking, camera helpers, audio sprites
- Performance visibility with built-in render stats and benchmark harness
- Optional Rapier physics integration without forcing physics on every app
Application,Scene, and scene-manager lifecycle- Typed
Loaderwith manifest/bundle workflow (defineAssetManifest,registerManifest,loadBundle) - Drawables:
Sprite,AnimatedSprite,Graphics,ParticleSystem,Text,Video - Scene stacking (
overlay/modal/opaque) with input routing and fade transitions - View/camera helpers (
follow, bounds clamp, shake, zoom) - Rendering composition primitives (
RenderTexture,RenderTargetPass, filter chains, masks, cache-as-bitmap) - Render stats (
submittedNodes,culledNodes,drawCalls,batches,renderPasses, ...) - Optional Rapier adapter (
createRapierPhysicsWorld)
npm install exojsimport { Application, Scene, Graphics, Color, type SceneRenderRuntime } from 'exojs';
class HelloScene extends Scene {
private readonly box = new Graphics();
public constructor() {
super();
this.box.fillColor = Color.white;
this.box.drawRectangle(-32, -32, 64, 64);
this.box.setPosition(400, 300);
this.addChild(this.box);
}
public override update(delta: import('exojs').Time): void {
this.box.rotation += delta.seconds * 45;
}
public override draw(runtime: SceneRenderRuntime): void {
this.root.render(runtime);
}
}
const canvas = document.querySelector('canvas');
if (!canvas) {
throw new Error('Missing <canvas> element.');
}
const app = new Application({
canvas,
width: 800,
height: 600,
clearColor: Color.cornflowerBlue,
});
await app.start(new HelloScene());- Documentation hub: docs/README.md
- Getting started: docs/getting-started/quickstart.md
- Core concepts: docs/core-concepts/overview.md
- Assets and bundles: docs/assets/loader-and-bundles.md
- Scenes and stack flow: docs/scenes/scene-flow.md
- Rendering and visuals: docs/rendering/visual-capabilities.md
- Audio workflow: docs/audio/audio-workflow.md
- Optional physics: docs/physics/rapier-integration.md
- Performance/debugging: docs/performance/performance-and-debugging.md
- API reference: docs/api/README.md
- In-repo examples: examples/README.md
Application defaults to backend auto-selection:
- prefers WebGPU when available
- falls back to WebGL2 if WebGPU is unavailable or initialization fails
You can force backend selection when needed:
new Application({ backend: { type: 'webgpu' } });
new Application({ backend: { type: 'webgl2' } });
new Application({ backend: { type: 'auto' } });Rapier integration is opt-in and loaded only when you use it.
import { createRapierPhysicsWorld } from 'exojs';
const physics = await createRapierPhysicsWorld({ gravityY: 9.81 });If Rapier is unavailable, creation fails with a clear setup error.
The runnable live site (Astro + Lit + Monaco preview) lives in examples/ and is deployed as the repository's GitHub Pages site at https://exoridus.github.io/ExoJS/.
npm run typecheck
npm run lint
npm test
npm run build
npm run verify:package
npm run perf:benchmarkInternal imports use the @/* path alias (mapped to src/*) — the same convention used by Vite, Next.js, and other modern TypeScript setups. Building the library requires TypeScript 6.
- Repository: https://github.com/Exoridus/ExoJS
- Issues: https://github.com/Exoridus/ExoJS/issues
- Changelog: CHANGELOG.md