Maze generation, solving, and editing for TypeScript.
📚 Documentation | 🧩 Mazely Studio | 📦 npm
Mazely is a TypeScript library for generating, solving, and editing mazes. Its core exposes algorithm progress as steps. Applications can run an algorithm to completion or consume its progress incrementally to build their own visualizations, teaching tools, games, and renderers.
- Twelve maze generation algorithms and five solving algorithms
- Deterministic generation with string or numeric seeds
- Square, triangular, and hexagonal grids with custom masks
- Step-by-step execution or immediate completion
- Transactional maze editing with lifecycle events
- JSON-safe maze serialization
- Framework-agnostic TypeScript API with ESM support
- Mazely Studio - an interactive maze playground for generating, solving, editing, and visualizing mazes.
- V-CONF × Mazely - interactive 3D Vue and Vite logo mazes for V-CONF.
| Package | Description |
|---|---|
mazely |
Recommended entry point with createMaze() defaults and the complete public API |
@mazely/core |
Lower-level algorithms, grid model, step engine, editing, and serialization |
Use mazely for applications and libraries. Reach for @mazely/core only when
you are assembling a lower-level runtime directly.
pnpm add mazelynpm install mazelyFor the core package directly:
pnpm add @mazely/coreimport { createMaze } from 'mazely'
const maze = createMaze({
grid: {
type: 'square',
cols: 21,
rows: 21,
},
seed: 42,
})
maze.generate('dfs', {
start: { x: 0, y: 0 },
}).finish()
maze.solve('a-star', {
start: { x: 0, y: 0 },
end: { x: 20, y: 20 },
}).finish()
const result = maze.getSolveResult()
console.log(result?.solved)
console.log(result?.path)
console.log(result?.visitedCount)createMaze() defaults to a 21 x 21 square grid. Pass grid when you need
explicit dimensions, a mask, or another supported topology.
Generation and solving return the same StepPlayer interface. Use next() to
apply one algorithm step, prev() to revert one, reset() to return to the
beginning, or finish() when only the completed result matters.
const player = maze.generate('prim')
function advance() {
if (!player.next())
return
const step = player.steps[player.index - 1]
renderMaze(maze.grid, step) // Your renderer
requestAnimationFrame(advance) // Your scheduler
}
requestAnimationFrame(advance)renderMaze() is application code, not a Mazely export. Each step contains
grid patches and may include a payload with from and to cell IDs.
Rendering, timing, pause/resume behavior, and playback controls remain under
application control. player.progress.totalSteps is null while the lazy
source still has unknown steps and becomes exact after completion.
import { createMaze } from 'mazely'
const maze = createMaze({
grid: {
type: 'square',
rows: 31,
cols: 31,
},
seed: 'repeatable-maze',
})
const generation = maze.generate('wilson')
generation.finish()The main package also exports algorithm factories, grid types, StepPlayer,
serialization helpers, seeded random utilities, and all public TypeScript
types.
Triangular grids use alternating up/down cells with at most three neighbors:
const triangle = createMaze({
grid: {
type: 'triangle',
layout: 'triangle',
size: 20,
},
seed: 'triangles',
})
triangle.generate('prim').finish()size is the number of smallest triangles along each side. A grid of size
n contains n² cells and has a triangular outer boundary.
Triangle and hexagonal grids support Aldous-Broder, Binary Tree, DFS, Eller's, Growing Tree, Hunt-and-Kill, Kruskal, Prim, Random Traversal, Recursive Division, Sidewinder, and Wilson generation.
Use a rectangular boundary when the outer shape should remain rectangular:
const triangleRectangle = createMaze({
grid: {
type: 'triangle',
layout: 'rectangle',
rows: 20,
cols: 40,
},
})Hexagonal grids have six neighbors per cell and support rectangular or
hexagonal outer boundaries. Choose pointy or flat orientation:
const hexagon = createMaze({
grid: {
type: 'hexagon',
layout: 'hexagon',
size: 10,
orientation: 'pointy',
},
seed: 'hexagons',
})
hexagon.generate('dfs').finish()Use { type: 'hexagon', layout: 'rectangle', rows, cols, orientation } for a
rectangular boundary. All grid types accept connected cell masks.
aldous-broderbinary-treedfsellergrowing-treehunt-and-killkruskalprimrecursive-divisionsidewindertraversalwilson
a-starbest-firstbfsdfsflood(breadth-first traversal without an end point)
Pass a boolean mask to include only selected cells. Excluded cells and their edges are absent from the grid, so generation and solving stay inside the shape.
import { createMaze } from 'mazely'
const maze = createMaze({
grid: {
type: 'square',
rows: 3,
cols: 3,
mask: [
[true, true, true],
[true, false, true],
[true, true, true],
],
},
})Generated mazes can be edited without bypassing the grid model:
maze.setEdgeOpenedBetween(
{ x: 0, y: 0 },
{ x: 1, y: 0 },
true,
)
maze.closeCell({ x: 2, y: 2 })
maze.openAllEdges()
maze.closeAllEdges()Edit callbacks are transactional: all targets are validated before changes are committed. A thrown callback leaves the topology and lifecycle state unchanged.
Serialize the grid topology and restore it into another compatible grid:
import {
applySerializedGrid,
createMaze,
serializeGrid,
} from 'mazely'
const source = createMaze({
grid: { type: 'square', cols: 15, rows: 15 },
seed: 7,
})
source.generate('kruskal').finish()
const saved = serializeGrid(source.grid)
const restored = createMaze({
grid: { type: 'square', cols: 15, rows: 15 },
})
applySerializedGrid(restored.grid, saved)const unsubscribe = maze.on('step', ({ state }) => {
console.log(state.index, state.totalSteps)
})
maze.on('complete', ({ state }) => {
console.log(`${state.phase} complete`)
})
unsubscribe()Available events are step, complete, reset, phaseChange, and edit.
Requirements:
- Node.js 24
- pnpm 10.28.0
git clone https://github.com/wujue0115/mazely.git
cd mazely
pnpm install
pnpm test:ciCommon commands:
| Command | Purpose |
|---|---|
pnpm build |
Build all packages and applications |
pnpm typecheck |
Type-check the complete workspace |
pnpm test |
Run the Vitest suites |
pnpm lint |
Run ESLint and formatting checks |
pnpm test:ci |
Run the complete release verification |
See CONTRIBUTING.md for the branching model, commit convention, and pull request checklist.
MIT Copyright (c) 2026-PRESENT Wujue.