DOM ENGINEV0.21.3FIZLET

01 DOCS · GETTING STARTED

Five minutes
to a running engine.

Fizlet is a micro game and animation engine for the DOM: one shared loop, bounded everything, and the page always comes back exactly as it was. The kernel is 3,372 B gzip (3.3 KB), with no runtime dependencies. This page gets an engine running and shows the four calls everything else builds on.

Load it

Pick one. All three ship the same code, built from the same source on every release (v0.21.3 today).

  1. One script tag. https://fizlet.com/fizlet.js puts the kernel and every brick but @fzlt/core/debug on window.fizlet. No build step. The quick start runs it as is.
  2. ES modules, only what you use. Import each brick from https://fizlet.com/dist/: index.js is the kernel, fx.js is @fzlt/core/fx, and so on. A page that imports the kernel and @fzlt/core/fx ships only those.
  3. npm. npm install @fzlt/core gives you every subpath export (@fzlt/core, @fzlt/core/fx, @fzlt/core/slot …) and its TypeScript types. Or build from source: git clone, npm ci, npm run build gives you the same dist/.
MODULES · game.ts
import { createEngine } from "@fzlt/core";

const root = document.querySelector("#game")!;
const engine = createEngine({ root, seed: 7 });
const sparks = engine.pool("sparks", 64, () => ({ x: 0, y: 0, vx: 0, vy: 0 }));

engine.add({
  read(e) { /* measure the page here, once a frame */ },
  step(e, dt) { /* the simulation: fixed 60 Hz, no DOM, no allocation */ },
  render(e, alpha) { /* change-only DOM writes through e.ledger */ },
});
engine.start();

// Later: Recall. Every listener goes, every page change is undone.
engine.destroy();

What each call does

  • createEngine({ root, seed }) makes an engine. root is the element it lives in: off screen, it pauses. seed feeds engine.random, so a run replays.
  • engine.pool(name, cap, create) makes every item up front. It never grows: when it is full, acquire() says no. That is contract rule 2.
  • engine.add(system) adds a system with up to four hooks: read (measure the page), step (simulate, at a fixed 60 Hz), render (write the page) and pause. The loop explains the order.
  • engine.start() joins the page's one shared requestAnimationFrame. engine.destroy() is Recall: every listener goes and every page change is undone.

Where next

  • The ideas

    Read the contract, then the loop, Recall, budgets and determinism. Each page is short and says which test proves it.

  • The bricks

    Input, collision, effects, sprites, sound, timelines, multiplayer and more, each its own import with its own size budget. Every brick page lists its whole API from the type declarations.

  • A first build

    Build a micro game end to end, or fill an Astro slot with a hero scene that costs nothing while it is still.