Cellular Automaton Lab is a browser-based cellular automata playground built around topology-first boards. It supports classic lattices, periodic mixed tilings, and finite aperiodic patches in one app, with a Flask backend and a Vite-built TypeScript frontend.
Public release status: v0.5.0 preview. The preview is usable for public evaluation, local experimentation, and contribution, but it is not a long-term API or feature-stability promise.
Live standalone demo: https://grgs.github.io/cellular-automaton-lab/
First time here? docs/ONBOARDING.md is a one-page decision tree -- find the row that matches what you want to do (run the app, add a tiling, use the topology library, etc.) and follow the link. The examples/ directory has short, runnable Python scripts for each major subsystem.
This project explores cellular automata on rectangular and non-rectangular boards. The rule engine, editor, renderer, and pattern format are organized around topology data so the same app workflow can run on square grids, hex grids, mixed periodic tilings, and finite aperiodic patches.
It is intended for comparing how familiar automata behave on different local neighborhoods, testing topology and rendering ideas, and saving sparse patterns by stable cell IDs rather than lattice-specific grid coordinates.
- 46 shipped tiling families (3 regular grids, 27 periodic mixed tilings, 16 aperiodic patches including Penrose variants and monotiles)
- 16 built-in rules spanning Life-like, mixed-tiling, excitable, and signal systems
- one shared
next_state(ctx)rule protocol across all shipped topologies - canvas-first editing with brush, line, rectangle, fill, undo/redo, presets, and pattern import/export
- compare workspace that runs one shared seed across many tilings, charts topology-sensitive outcomes, plays synchronized side-by-side filmstrips, saves named runs locally, and opens any result generation back into build mode (also scriptable via
python -m tools tilings compare) - sparse pattern persistence keyed by stable topology cell IDs
- TypeScript frontend in
frontend/with Vitest unit tests and Playwright browser coverage
- Start with Square + Conway, paint a few cells, use step/run, then export or copy the pattern to see the sparse
cells_by_idformat. - Switch to Kagome or
4.8.8, choose the matching mixed-tiling Life rule, and open the inspector while painting to see the same editor workflow on non-square neighborhoods. - Switch to Penrose P3 Rhombs, Spectre, or Taylor-Socolar, adjust patch depth, and watch how a finite aperiodic patch remains editable and persistent.
- Compare
Penrose P1 Pentagon-Diamond (Distributed)withPenrose P1 Pentagon-Boat-Starto see the difference between the distributed vertex-merge manifestation and the centered singular pentagrid patch. - Try the convex pentagonal periodic catalog with Cairo, Prismatic, Floret, Type 7, Stein 14, and Pentagon Crosses to compare how the same rule family behaves on distinct pentagon adjacencies.
- Try Whirlpool or HexWhirlpool from the preset/showcase controls for a quick multi-state animation that exercises more than binary Life-like states.
- Open
#/compareor use the floating compare button to compare one seed across tilings. Use Run comparison for the phase portrait/table, Play side by side for synchronized boards, and Open gen N on a live board to bring that generation back into build mode. - Reload the standalone GitHub Pages demo after changing topology or state to check browser persistence without the Flask server.
Compare mode is available from the floating Compare tilings button or directly at #/compare. It uses a shared seed, rule, traversal, frame count, and grid size so each selected tiling starts from comparable conditions. The tiling checklist and presets define the side-by-side panes; unsupported rule/tiling combinations are disabled in the picker and rejected by the backend if submitted directly.
The workspace has two run paths:
- Run comparison returns a phase portrait plus a result table. Each row can open or copy the begin/end board state as a normal
#share=v1...board link. - Play side by side builds a synchronized filmstrip. Play, pause, step, reset, scrub, and speed controls operate one shared clock across all boards. Each board has an Open gen N action that loads its current generation into build mode.
Use Copy run link to create a #/compare&run=v1.<base64url-json> URL. Opening that link restores the compare setup without auto-running or auto-playing, so cold loads do not start surprise work. Use Saved runs and Saved tiling sets to keep named compare setups in browser localStorage; they work in both the Flask app and the standalone demo, but they are local to the current browser/device. Run links are the portable format.
Current limits are intentional for interactive use: live filmstrips are bounded to a small selected set of tilings and a capped frame count by the backend, and compare mode is designed around one shared seed/rule configuration rather than independent per-pane rules.
- The simulation model is topology-first: rules evaluate cells through a neighbor context rather than direct grid indexing.
- The backend owns canonical simulation state; the browser renders snapshots and sends explicit mutations.
- Regular, mixed periodic, and aperiodic boards share the same rule protocol and editing workflow.
- Pattern files use sparse
cells_by_idpayloads instead of dense grid-only formats. - The standalone build runs the Python simulation stack in a browser worker through Pyodide, so server and static-host demos share the same backend model.
For deeper orientation, start with:
- Architecture for runtime boundaries and subsystem ownership
- Code map for file-level navigation and call paths
- Contributing for setup, common commands, and contribution expectations
- Maintenance for guardrails, release process, and doc ownership
- Install Python dependencies:
py -3 -m pip install -r requirements.txt- Install frontend dependencies:
npm install- Build the frontend bundle:
npm run build:frontend- Start the app:
py -3 .\app.pyThe server respects HOST, PORT, and APP_INSTANCE_PATH. If static/dist/manifest.json is missing, startup fails with a message telling you to run npm run build:frontend.
The canonical "what to run" list lives in docs/ONBOARDING.md. At a glance:
npm run check:frontend # frontend lint + build + vitest
npm run check:python # ruff lint + ruff format check + mypy
npm run check:ci-local # the broad local-CI sweepFor choosing narrower checks by change type, see Testing changes. For the full strategy, browser diagnostics, and the release-confidence sweep, see Testing strategy and Maintenance.
- Adding rules
- Adding topologies
- Adding presets and patterns
- Choosing tests for changes
- Tools reference
The public v0.5.0 preview ships through three surfaces:
- tagged GitHub source releases
- the GitHub Pages standalone demo
- local source checkout for development and self-hosted use
This release does not publish an npm package or a PyPI package. The repository is the install and integration surface for now.
pinwheelandpinwheel-2-1both ship in the mainAperiodicgroup:pinwheelwas promoted on June 12, 2026 after correcting its subdivision shear, andpinwheel-2-1on June 13, 2026 after a visual review against the published Bielefeld patch (its exact-Fraction1:4:sqrt(17)tiles are congruence-verified at every depth).dodecagonal-square-triangleis currently implemented as a decorated3.12.12Archimedean generator rather than the canonical Schlottmann quasi-periodic square-triangle tiling.- The standalone GitHub Pages demo targets static hosting with network access and still loads Pyodide from a CDN rather than bundling it for offline use.
The canonical list of known mathematical and rendering deviations lives in docs/TILING_KNOWN_DEVIATIONS.md. Active follow-up work lives in TODO.md.
- No npm or PyPI package is published; the source repo and standalone demo are the release surface.
- No public plugin or extension API is promised yet.
- No separate JavaScript simulation engine is maintained for the standalone demo; the browser runtime reuses the Python backend through Pyodide.
- No full offline standalone bundle is shipped yet because Pyodide still loads from a CDN.
- No claim is made that every aperiodic family is a complete symbolic or literature-canonical construction; weaker or provisional cases are documented in the tiling deviation notes.
app.py: local app entrypointbackend/: Flask app, simulation engine, rules, topology catalog, persistence, and API routesfrontend/: authored TypeScript frontend sourcestatic/css/: authored stylesstatic/dist/: generated frontend build outputtemplates/: HTML shelltests/: backend, API, integration, and browser coveragetools/: validation, build, diagnosis, and profiling helpers


