Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sanchedev/tiny-engine/llms.txt

Use this file to discover all available pages before exploring further.

tiny-engine lets you build 2D browser games using JSX syntax backed by a completely custom runtime. There is no React, no virtual DOM, and no DOM rendering at all — JSX compiles directly to a canvas-based scene graph using the tiny-engine/jsx-runtime. If you already know hooks-style APIs (useSignal, useEffect, useComputed), you already know most of tiny-engine.

Quickstart

Install the package, configure TypeScript, and render your first scene in under five minutes.

Nodes

Every visual and logical element in a scene is a node: transform, sprite, clickable, collider, timer, and more.

Reactivity

Signals and computed values propagate changes directly to canvas properties without any diffing pass.

JSX Runtime

Learn how tiny-engine/jsx-runtime turns JSX expressions into node trees at construction time.

How it works

When TypeScript compiles your JSX, it calls tiny-engine/jsx-runtime instead of React.createElement. The runtime builds a plain description tree (Tiny.Node) that renderToNodes (exported from tiny-engine/jsx) walks to construct real node instances — classes like Transform, Sprite, and Clickable. Each node has its own start, update, and draw lifecycle. The top-level Game class drives a requestAnimationFrame loop that clears the canvas, calls update on the active scene’s root node, runs the collision system, and then calls draw top-down through the node tree. There is no reconciler; once a node is constructed it stays in the tree until explicitly destroyed. Reactivity is layered on top via signals. When you write:
<sprite brightness={() => 0.5 + health() / 200} />
the arrow function is stored as a SignalGetter on the node’s brightness property. Each frame, reading that property re-evaluates the function and updates the canvas draw call automatically — no re-render, no diffing.

Project structure

tiny-engine is a pnpm monorepo with two packages:
PackageDescriptionBuild
tiny-engineCore engine librarypnpm engine:build
demoPlants vs Zombies-style example gamepnpm demo:build
The demo package is a fully playable game that demonstrates assets, collision, animation, scenes, and scripts. It is the best reference for real-world usage patterns.
pnpm dev           # Run engine + demo in watch mode
pnpm engine:build  # Compile the engine (tsc)
pnpm demo:dev      # Serve the demo (esbuild)
pnpm lint          # Run ESLint checks

Sub-path exports

The package is split into focused entry points so you only import what you need:
Entry pointWhat it contains
tiny-engineCore nodes, collision system, asset loading (loadTexture), math utilities (Vector2), and Game/Scene classes
tiny-engine/hooksuseSignal, useComputed, useEffect, useEvent, useRefNode, useRef, useMount, useScript, useSpawn, useChild, useGame, useContext, createContext, NodeReference
tiny-engine/jsxcreateGame, renderToNodes, and the JSX components Game, Scene, List, Fragment
tiny-engine/scriptsTinyScript abstract class for separating game logic from the component tree
tiny-engine/jsx-runtimeThe custom JSX transform consumed by TypeScript — you never import this directly
tiny-engine is built with verbatimModuleSyntax enabled. When importing types, use import type syntax:
import type { SignalGetter } from 'tiny-engine'
The package ships with strict TypeScript types throughout. All node option interfaces, signal generics, and event callbacks are fully typed — no any escape hatches in the public API.

Build docs developers (and LLMs) love