Automata π¦ β caza.la/automata
A framework-agnostic TypeScript library for building real-time cellular automata with WebGPU. Explore neural CA, Gray-Scott reaction-diffusion, Lenia, Pokemon type battles, life-like and Wolfram rules, or write your own rule in WGSL.
- WebGPU compute: advance large cell grids in parallel and render directly from GPU storage buffers.
- Ten built-in automata: neural CA, trainable Growing Neural CA, reaction-diffusion, Lenia, Pokemon, Life, Larger than Life, elementary rules, Brian's Brain, and cyclic automata.
- Tuned starting states: each rule provides useful defaults, presets, render hints, and seeding designed for its dynamics.
- Realtime controls: update declared parameters with uniform writes and no pipeline rebuild.
- Custom WGSL rules: use
createAutomaton()for a compact rule definition or subclassAutomatonfor storage buffers and structural state. - Camera and interaction helpers: resize, zoom, pan, paint, erase, and grow a grid while preserving its contents.
- Framework-agnostic core: use the library from React, Vue, Svelte, or vanilla JavaScript, with no runtime dependencies.
- Interactive playground: tune six visual automata on desktop or mobile at caza.la/automata.
Read the searchable documentation site or
browse its Markdown sources in docs/:
- Getting started: embed a simulation, choose a grid, seed a rule, tune parameters, and add pointer interaction.
- Built-in automata: parameters, presets, seeding behavior, tuning notes, and performance characteristics for every rule.
- Writing custom automata: define WGSL rules, realtime parameters, storage buffers, render hints, and custom seeds.
- Architecture: compute and render pipelines, ping-pong buffers, frame scheduling, camera behavior, and playground design.
- Contributing: development setup, repository layout, conventions, and verification workflow.
This repository is a pnpm monorepo containing:
@cazala/automata β core library
The zero-dependency TypeScript package. It contains the WebGPU engine, camera, built-in rules, and framework for custom automata.
playground β interactive application
A React, Redux, and Vite application that showcases six automata with live parameters, presets, pointer tools, responsive controls, and mobile pinch zoom. It also serves as the integration reference and manual test bed.
worker β Cloudflare edge proxy
A route-scoped Cloudflare Worker that serves the Pages deployment at
https://caza.la/automata while proxying https://automata.caza.la. It keeps
the public URL on the main domain and forwards playground and documentation
assets under the /automata path.
Install the core library:
npm install @cazala/automataCreate an engine, seed its automaton, and start the simulation:
import { Engine, Neural, gridForCanvas } from "@cazala/automata";
const canvas = document.querySelector<HTMLCanvasElement>("#automata")!;
const engine = new Engine({
canvas,
automaton: new Neural(), // defaults to the "worms" rule
grid: gridForCanvas(canvas.clientWidth, canvas.clientHeight),
stepsPerSecond: 120,
});
await engine.initialize();
engine.coverGrid(); // center the camera and cover the canvas
engine.reset(); // use the automaton's tuned initial state
engine.autoResize(); // follow container resizes
engine.play();This is enough for a complete animated site background. initialize() rejects
with a descriptive error when WebGPU is unavailable, so an application can
keep a CSS or static-image fallback.
| Class | System | Highlights |
|---|---|---|
Neural |
Convolutional neural CA or an injectable two-layer MLP substrate | Worms, mitosis, mosaic, trained weights, and network presets |
GrowingNeural |
Differentiable morphogenesis rule from Growing Neural Cellular Automata | Serializable trainer artifacts, stochastic residual updates, exact pre/post life mask, regeneration |
ReactionDiffusion |
Gray-Scott two-chemical model | Coral, mitosis, solitons, worms, and waves |
Lenia |
Continuous Life with a radial kernel and growth function | Realtime mu, sigma, and dt; structural radius |
Pokemon |
18-type battle CA using the type-effectiveness chart | Coherent domains and adjustable battle threshold |
Life |
Any life-like birth/survival rule | Conway, Day & Night, maze, and coral presets |
LargerThanLife |
Large Moore neighborhoods with range rules and cooldown states | Bosco, Majority, Waffle, and multistate presets |
Elementary |
Wolfram rules 0β255 rendered as scrolling history | Presets for visually interesting rules |
BriansBrain |
Three-state firing/refractory automaton | Glider-rich dynamics |
Cyclic |
Each state is consumed by its successor | Rotating spiral patterns |
Each class declares its parameter specifications and recommended simulation rate; automata with presets expose them as static maps. The automata catalog covers the rule-specific details and why their seeds matter.
The engine stores width Γ height Γ channels floating-point values in two GPU
buffers. Each compute step reads the current buffer, writes the next buffer,
then swaps them. A fullscreen render pass colorizes the newest state without a
CPU readback.
- Realtime changes such as
automaton.set("feed", 0.05)update a uniform and take effect on the next step. - Structural changes such as replacing an automaton, changing grid or channel dimensions, or updating Lenia's baked radius rebuild the affected buffers and pipelines.
Wrap a WGSL update body with createAutomaton():
import { createAutomaton } from "@cazala/automata";
const decay = createAutomaton({
name: "decay",
channels: 1,
params: [
{ name: "rate", type: "f32", default: 0.98, min: 0.5, max: 1 },
],
step: `setCell(x, y, 0, sampleAt(x, y, 0) * params.rate);`,
});The custom automata guide documents shader helpers, parameters, storage buffers, render hints, seeding, and debugging.
Neural network mode can load a complete two-layer MLP:
const neural = new Neural({
mode: "network",
activation: 1, // tanh
weights: {
channels,
hidden,
inputToHidden,
hiddenBias,
hiddenToOutput,
outputBias,
},
});The artifact uses row-major [hidden][channels Γ 4] and
[channels][hidden] matrices. Call setNetworkWeights(...) to replace
same-shape GPU weights without rebuilding, and getNetworkWeights() for a
deep-copying snapshot. The Neural catalog
documents validation, perception ordering, and serialization.
GrowingNeural implements the two-phase update rule from
Growing Neural Cellular Automata:
identity/Sobel perception, a shared ReLU MLP, stochastic residual updates, and
the alpha-channel pre/post life mask.
import { Engine, GrowingNeural } from "@cazala/automata";
const artifact = await fetch("/models/butterfly.json").then((r) => r.json());
const automaton = GrowingNeural.fromArtifact(artifact);
const engine = new Engine({
canvas,
automaton,
grid: { width: 72, height: 72, wrap: false },
render: { colorBg: { r: 1, g: 1, b: 1, a: 1 } },
});
await engine.initialize();
engine.coverGrid();
engine.reset({ mode: "center" });
engine.play();The versioned JSON artifact stores [hidden][channels Γ 3] and
[channels][hidden] matrices plus the fire rate, step size, and life-mask
semantics. getArtifact() produces a JSON-safe object, while setWeights()
replaces same-shape GPU weights without rebuilding. The repository also
includes pnpm convert:growing-ca for converting the official TensorFlow.js
graph exports.
pnpm install
pnpm dev # playground at http://localhost:3000
pnpm dev:docs # docs at http://localhost:5173/automata/docs/
pnpm build # core + playground + static docs
pnpm type-check # core build + playground typecheckThe production workflow builds the playground with a /automata/ base, then
builds the VitePress site into packages/playground/dist/docs. Cloudflare
Pages deploys the combined artifact and the worker exposes it on caza.la.
- Simulation rate is independent from display refresh rate; the engine caps per-frame backlog to prevent a slow frame from causing a death spiral.
gridForCanvas()chooses a grid from the canvas size and caps each dimension to keep fullscreen simulations bounded.- Lenia and Larger than Life are the most expensive built-ins because their work scales with neighborhood area; reaction-diffusion and small-neighborhood rules can run many more steps per second.
- A WebGPU-capable browser is required. Recent Chrome, Edge, and Safari releases
are supported; applications should provide a fallback when
initialize()cannot acquire a GPU device.