Reference
Packages

Packages

Mirage Engine is a pnpm monorepo. mirage-engine is the package you normally install; the rest are published so you can pick just one piece.

PackagenpmDepends on
mirage-engine↗ (opens in a new tab)core, painter, sandwich
@mirage-engine/core↗ (opens in a new tab)painter, dom-tracker, wasm-compute
@mirage-engine/painter↗ (opens in a new tab)three (peer)
@mirage-engine/dom-tracker↗ (opens in a new tab)—
@mirage-engine/sandwich↗ (opens in a new tab)dom-tracker
@mirage-engine/wasm-computeinternalRust / wasm-bindgen

  • @mirage-engine/core

    Everything except the facade. Use it if you are building your own wrapper.

    import { Engine, WasmSynchronizer } from "@mirage-engine/core";
    import type { CoreConfig, SceneNode, Quality } from "@mirage-engine/core";

    Engine

    MethodSignatureNotes
    constructor(target, config: CoreConfig)Injects styles, resolves container, builds Renderer + Syncer
    start(): Promise<void>Boots wasm, starts the tracker
    stop(): voidStops the tracker
    dispose(): voidStops and disposes the renderer
    getTracker(): TrackerUnderlying DOM tracker
    getCanvas(): HTMLCanvasElementMounted canvas
    updateUniforms(el, uniforms): voidFast-path uniform write

    Also exported: the full type surface (SceneNode, NodeRect, Visibility, THREE_LAYERS, ATTR_* constants, DIRTY_* flags, WASM_STRIDE and the OFFSET_* indices).


    @mirage-engine/painter

    DOM-accurate Three.js materials, standalone. No DOM observation — you supply the styles.

    import { Painter, TextGenerator, createBoxMaterial } from "@mirage-engine/painter";

    Painter

    Painter.create(
      type: "BOX" | "TEXT",
      styles: BoxStyles | TextStyles,
      content: string,
      width: number,
      height: number,
      quality?: number,
      texture?: THREE.Texture | null,
      shaderHooks?: ShaderHooks,
    ): THREE.Material
     
    Painter.update(material, type, styles, content, width, height, quality?, texture?): void
     
    Painter.forceUpdateUniforms(material: THREE.ShaderMaterial, values: BoxUniformValues): void
    import * as THREE from "three";
    import { Painter } from "@mirage-engine/painter";
     
    const material = Painter.create("BOX", {
      backgroundColor: "rgb(20, 20, 30)",
      backgroundImage: "linear-gradient(45deg, #f00, #00f)",
      opacity: 1,
      zIndex: 0,
      borderRadius: "16px",
      borderColor: "rgba(255,255,255,0.2)",
      borderWidth: "2px",
      boxShadow: "0 8px 24px rgba(0,0,0,0.4)",
    }, "", 320, 180);
     
    const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material);
    mesh.scale.set(320, 180, 1);

    TextGenerator

    A THREE.MeshBasicMaterial subclass that paints text onto a CanvasTexture.

    const mat = new TextGenerator("Hello", textStyles, 200, 40, 2);
    mat.updateText("Goodbye", textStyles, 200, 40);
    mat.dispose();

    CSS parsers

    parsePixelValue, parseColor, splitByComma, parseLinearGradient and parseBoxShadow are exported for reuse. They accept the string forms getComputedStyle returns.

    import { parseLinearGradient } from "@mirage-engine/painter";
     
    parseLinearGradient("linear-gradient(45deg, red 0%, blue 100%)");
    // { angle: 0.785…, stops: [ { color, alpha, stop }, … ] }

    @mirage-engine/dom-tracker

    Batched DOM observation with no rendering opinion. Zero dependencies.

    import { Tracker, extractFromStyle } from "@mirage-engine/dom-tracker";
     
    const tracker = new Tracker(document.body, { resizeDebounce: { delay: 200 } });
     
    tracker.onLayoutChange.add((mask, deletions) => { /* … */ });
    tracker.onStyleChange.add((styles) => { /* Map<HTMLElement, StyleData> */ });
    tracker.onRender.add(() => { /* every frame */ });
     
    tracker.start();
    HookPayloadFires
    onBeforeRender—Every frame, first
    onLayoutChange(mask: number, deletions: Set<HTMLElement>)Only when the tree is dirty
    onScrollChange(scrollX, scrollY)When window scroll changed
    onStyleChangeMap<HTMLElement, StyleData>When inline styles mutated
    onRender—Every frame, last

    Each hook is a Set, so add / delete manage subscriptions.

    Mirage itself subscribes to onLayoutChange, onStyleChange and onRender. onScrollChange fires but has no built-in subscriber — it is there for you.


    @mirage-engine/sandwich

    DOM teleportation: lift elements above a canvas while keeping page layout intact.

    import { SandwichRenderer } from "@mirage-engine/sandwich";
     
    const sandwich = new SandwichRenderer({ frontSelector: "[data-hud]" });
    sandwich.init();
    MethodPurpose
    init()Create layers, hijack front elements, wire hooks, start the tracker
    useTracker(tracker)Reuse an existing tracker instead of creating one

    Mirage calls useTracker(engine.getTracker()) automatically so both share one requestAnimationFrame loop.


    @mirage-engine/wasm-compute

    Rust crate compiled with wasm-pack. Not meant for direct use.

    pub struct MemoryManager { /* Vec<f32> */ }
     
    impl MemoryManager {
        pub fn new(capacity: usize) -> MemoryManager;
        pub fn get_pointer(&self) -> *const f32;
        pub fn get_length(&self) -> usize;
        pub fn update_physics(&mut self, node_count: usize);
    }

    Layout is five floats per node:

    [ parentIndex, localX, localY, worldX, worldY ]

    update_physics walks nodes in order, adding each parent's world position to the child's local offset. Because extraction emits parents before children, one forward pass resolves the whole tree.


    Mirage Engine — MIT Licensed © 2026 dltldn333