Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sanchedev/fraxel/llms.txt

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

This guide walks you through installing Fraxel, configuring your TypeScript project to use the custom JSX runtime, and building a working game scene complete with textures, reactive state, and player input. You will have a canvas rendering on screen by the end of Step 3.
1
Install Fraxel
2
Add the fraxel package to your project using your preferred package manager:
3
npm
npm install fraxel
pnpm
pnpm add fraxel
yarn
yarn add fraxel
4
Fraxel has no runtime dependencies. The package includes the engine, the custom JSX runtime, all built-in nodes, hooks, and the asset pipeline.
5
Configure tsconfig.json
6
Fraxel provides its own JSX transform through a custom jsxImportSource. You must configure TypeScript to use it instead of React:
7
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "verbatimModuleSyntax": true,
    "jsx": "react-jsx",
    "jsxImportSource": "fraxel"
  }
}
8
verbatimModuleSyntax: true requires that type-only imports use the explicit type keyword. For example, write import type { GameControls } from 'fraxel/jsx' for any import that is used only as a TypeScript type. Regular value imports (import { useSignal } from 'fraxel/hooks') are not affected.
9
The critical options are:
10
  • jsx: "react-jsx" — tells TypeScript to use the automatic JSX transform (i.e. jsx/jsx-runtime)
  • jsxImportSource: "fraxel" — points the automatic transform to fraxel/jsx-runtime instead of react/jsx-runtime
  • 11
    With these two options set, every .tsx file in your project will use the Fraxel engine as its JSX runtime automatically. No import needed.
    12
    Create Your First Game
    13
    Create a main.tsx file at your project root. This example loads two textures, defines a scene as a JSX function, wires it into a <Game> configuration, and starts the game loop:
    14
    import { createGame, Game, Scene } from 'fraxel/jsx'
    import { loadTexture } from 'fraxel/assets'
    
    // Load textures before creating the game.
    // loadTexture returns a symbol ID used to reference the texture in JSX.
    const BG = await loadTexture('/assets/background.png')
    const PLAYER = await loadTexture('/assets/player.png')
    
    // A scene component is a plain function that returns JSX.
    const scene = () => (
      <transform>
        <sprite textureId={BG} />
        <sprite textureId={PLAYER} position={[80, 50]} />
      </transform>
    )
    
    // createGame processes the JSX tree, creates the canvas, and mounts it
    // inside the element matched by the selector.
    const game = createGame(
      <Game width={192} height={112} defaultScene="main">
        <Scene name="main" component={scene} />
      </Game>,
      document.querySelector('#root')!,
    )
    
    game.play()
    
    15
    createGame calls game.play() internally to start the requestAnimationFrame loop immediately after setup. The explicit game.play() call at the end is only needed if you paused the game or want to defer startup — it is safe to call it again.
    16
    Here is what each piece does:
    17
  • loadTexture(url) — fetches an image and returns a symbol identifier. Pass this symbol to any textureId prop.
  • createGame(jsx, root) — processes the <Game> JSX tree, calls Game.setup() with the declared dimensions, registers each <Scene>, and sets the default scene.
  • <Game> — declarative game configuration. width and height define the canvas resolution. defaultScene names the scene that loads immediately.
  • <Scene> — registers a named scene. The component prop accepts a plain function or a lazy () => import(...) for code splitting.
  • game.play() — starts the requestAnimationFrame loop.
  • 18
    Add Interactivity
    19
    Use hooks inside your scene components to add reactive state, events, and per-frame logic. Here is a Player component that moves across the screen and turns grayscale when health reaches zero:
    20
    import { useNode, useEvent, useSignal } from 'fraxel/hooks'
    import { PrimaryNode } from 'fraxel'
    
    function Player() {
      // useNode creates a typed reference. Pass it to a node's `ref` prop.
      const sprite = useNode(PrimaryNode.Sprite)
    
      // useSignal returns a [getter, setter] tuple.
      // Call health() to read the value — calling it inside a prop function
      // registers it as a dependency automatically.
      const [health, setHealth] = useSignal(100)
    
      // useEvent subscribes to a node lifecycle event.
      // 'updated' fires every frame with the delta time in seconds.
      useEvent(sprite, 'updated', (delta) => {
        sprite.node.position.x += delta * 50
      })
    
      return (
        <sprite
          ref={sprite}
          textureId={PLAYER}
          grayscale={() => (health() <= 0 ? 1 : 0)}
        />
      )
    }
    
    21
    useEvent(sprite, 'updated', ...) is the idiomatic way to run per-frame logic in Fraxel. The delta argument is the time elapsed since the last frame in seconds, giving you frame-rate-independent movement without managing your own timers.
    22
    Plug the Player component into your scene:
    23
    const scene = () => (
      <transform>
        <sprite textureId={BG} />
        <Player />
      </transform>
    )
    

    Import Paths

    Fraxel is split across six sub-path exports so you only import what you use. Each path is independently tree-shakeable:
    // Main entry — nodes, math, collision shapes, core classes, reactivity primitives
    import { PrimaryNode, Vector2, shapes } from 'fraxel'
    
    // Hooks — all hooks for state, effects, lifecycle, and scene control
    import { useNode, useEvent, useSignal, useEffect, useMount, useComputed, useSpawn } from 'fraxel/hooks'
    
    // JSX components — createGame, Game, Scene, List, Fragment
    import { createGame, Game, Scene } from 'fraxel/jsx'
    
    // Assets — texture and sound loading
    import { loadTexture, loadBatch, loadSound } from 'fraxel/assets'
    
    // Animation & tweening — sprite sheets, tweens, easing functions
    import { tween, easeOutQuad, animationFromSheet } from 'fraxel/animation'
    
    // Scripts — FraxelScript base class for separating logic from rendering
    import { FraxelScript } from 'fraxel/scripts'
    
    With verbatimModuleSyntax: true in your tsconfig, any import used only as a type must use import type. For example: import type { GameControls } from 'fraxel/jsx'.

    Next Steps

    Core Concepts

    Understand the node tree, signal reactivity, and how the JSX runtime works under the hood.

    Nodes Reference

    Explore every built-in JSX element: <transform>, <sprite>, <collider>, <camera>, <text>, and more.

    Hooks API

    Full reference for useSignal, useComputed, useEffect, useMount, useNode, useEvent, and useSpawn.

    Build docs developers (and LLMs) love