DocsZones

Grids & boards

A grid turns a zone into a structured board: a chessboard, a hex wargame map, a point-to-point route network, or an open lattice that tiles snap to. A grid lives on a zone whose role is grid and whose arrangement is grid — the grid spec then describes the cells, nodes, and edges components can sit on.

Like everything else in taybl, a grid is scaffold, not a rules engine. It gives components named spots to land on; it never enforces legal moves, adjacency, or turn order. Players move pieces between cells by hand.

The four grid types

A grid’s type picks how its spots are laid out:

typeUse it forNotes
squareA rank-and-file board (chess, checkers)Needs either a cells list or both width and height
hexA hex map (Catan, wargames)Same cell rules as square, plus an orientation
graphA point-to-point network (Pandemic, Ticket to Ride)Defined by nodes + connections rather than a cell block. You build this one yourself — see below
openAn unbounded tile lattice (Carcassonne, dungeon crawls)No fixed cells; tiles snap to an openGrid lattice at runtime

A generated game never arrives as a graph board. When taybl builds a game from your uploads, a map, a route network or any board of scattered irregular positions comes back as an open play zone: your board art with the pieces sitting exactly where setup put them, free to be dragged anywhere. That is the honest default — a guessed network of nodes and routes puts every piece in the wrong place, and you would have to move all of them by hand. A node graph is a deliberate choice you make when you want pieces to snap: select the zone, set Arrangement to grid, then pick Node graph as the grid type and drop your own nodes.

A fixed square/hex grid renders unpainted by default — no grey background, so you can drop in your own board art as a surfaceAsset. Cells with an explicit color still show it; to see empty cell boundaries, turn on Show grid lines (gridLinesVisible).

Cells, nodes, edges, regions

Depending on the type, a grid is built from a few kinds of part:

FieldTypeMeaning
width / heightnumber .optional()Cell-block dimensions for a square/hex grid; an alternative to listing cells
cellsarray .optional()Explicit positioned cells — each an id, plus optional coordinates (axial {q, r, s}, how hex boards are positioned), offset (table units), label, color, region. On a hex board this list is the board: a hex exists exactly when it has an entry
orientationflat | pointy .optional()Hex lattice rotation. flat = a flat edge at 12 o’clock; pointy = a vertex at 12 o’clock. Must match the hex tile art. Default flat
nodesarray .optional()Vertices / intersections — placement targets distinct from cells (a Catan settlement spot, a Pandemic city)
connectionsarray .optional()Edges between cells / nodes (see below)
regionsarray .optional()Named groups of cellIds (a board’s territories or sectors). On a board with no surface art, a region also lends its name and a tint to each of its cells — see below
openGridobject .optional()Required when type is open: the lattice (square | hexPointy | hexFlat), cellSize, and optional autoFit, spacing, gridLinesVisible (see below)
openGrid.cellSizeobjectThe tile pitch (table units). Hex lattices auto-tessellate — tiles touch regardless of the authored width/height ratio, so you set one cell size (the tile’s long axis)
openGrid.spacingnumber .optional()Extra gap between tiles as a fraction of the pitch. 0 / unset = tiles touch; 0.15 = a 15% gap. The tile size is unchanged — only the spacing grows
openGrid.autoFitboolean .optional()Tiles scale down so the whole lattice fits inside the zone box
openGrid.gridLinesVisibleboolean .optional()Draw faint cell outlines across the board box — a graph-paper placement guide. Default (unset) = hidden; suppressed when the zone has printed surface art
openGrid.alwaysSnap / openGrid.neverSnapstring[] .optional()Component ids that override how a dropped piece is placed on the lattice. By default a piece snaps to a cell only when it covers at least half a cell (tiles snap; smaller meeples/markers free-place at the exact point). List a component under alwaysSnap to force it onto cells, or neverSnap to always free-place it. Set from the Grid card’s Snapping behavior control
nodeSizenumber .optional()Default node-marker radius (table units) for a graph grid
nodesVisibleboolean .optional()Whether node markers + routes are drawn during play. Default (unset) = hidden — the graph is an invisible scaffold so pieces sit on the printed board art
freePlacementboolean .optional()graph grids only. Whether the open area around the nodes accepts pieces. Default (unset) = allowed; set false for a strict node-only board. Set from the graph inspector’s Allow pieces anywhere on the board checkbox
fitobject .optional()A sub-rectangle of the zone box (fractions, 0..1) the cell block fills — aligns cells over board art whose printed grid doesn’t span the whole image
gridLinesVisibleboolean .optional()Draw faint grid lines for a fixed square/hex grid — a placement guide when the zone has no board image. Default (unset) = hidden; the grid is otherwise unpainted, so players can drop in their own board art. Suppressed over printed surface art
fillCellsboolean .optional()Pieces and tokens on this board render at their cell’s size instead of their own. Default (unset) = each piece keeps its own size
fillZoneboolean .optional()square grids only. The cell block stretches to fill the zone box, so cells take the box’s shape. Default (unset) = cells stay square and the block is centred, leaving felt on the long axis

Making pieces fill their cell

By default a piece on a board renders at its own size — the size set on the component — which is what you want when a piece is deliberately smaller than its cell: a number chit on a Catan terrain hex, a scoring marker on a track space. On an abstract board it is usually not what you want: a chess king drawn to fill its square ends up floating small in the middle of it.

Turn on Pieces fill their cell (fillCells) and every piece and token snapped to a cell takes the cell’s size instead. It applies to square and hex boards. Cards on a cell already fill it, with or without this setting.

If a piece still needs breathing room inside its square, give the component a padding value — that inset is applied on top, so you keep per-component control without going back to hand-tuned sizes. Ask Pip “make the pieces fill their squares” and it will set this for you.

Making the grid fill its zone

By default a square/hex grid keeps its cells square. If the grid’s shape doesn’t match the zone box you drew — a 10×5 grid in a box that isn’t twice as wide as it is tall — the block is centred and shrunk to fit, and felt shows above and below (or left and right) of it. That is the right default for a chess, go or checkers board, where a stretched square would be wrong.

When you drew the zone box to be the shape you want the grid to be, turn on Grid fills the zone (fillZone). Cell width and cell height are then worked out separately from the box, so the grid lands edge-to-edge with no padding around it. Combine it with fit to stretch the block across a sub-rectangle of the box instead of the whole thing. Ask Pip “make the grid fill the zone” and it will set this for you.

It applies to square grids only. A hex cell has to stay regular — the hex lattice drawn over the board is pitched off a single cell size, so a stretched hex would slide out from under its own guide. Size a hex board by its Cell size instead.

Connections (edges)

A graph grid’s connections[] are the edges between nodes (or cells). An edge with an id becomes a placement target itself — a road between two cities, a Ticket to Ride route you drop train cars onto:

FieldTypeMeaning
from / tostringThe two endpoints (cell, node, or open id)
idid .optional()When set, the edge is a droppable placement target
bidirectionalboolean .optional()Equivalent to directed: false. Mutually exclusive with directed
directedboolean .optional()true = traversal only fromto (a one-way segment). Default = undirected

The open area around a graph’s nodes

A graph board is more than its nodes and routes. The rest of it — the ocean on a Pandemic map, the margin beside a route network, the corner where you park the cubes you haven’t used yet — is open play by default: drop a piece there and it stays exactly where you released it.

Nodes and routes still win. A drop that lands on a city goes to that city, exactly as before; only a drop that misses every node, route and cell is free-placed. Free-placed pieces are stored as a freepoint_x_y position — the same thing an Open play (freeform) zone uses — so you can also pin one in setup by dragging a component from the library straight onto the map.

Turn it off with Allow pieces anywhere on the board in the graph inspector if your board should be strictly node-only. (Before this existed, a drop that missed every node made the piece disappear — it stayed in the zone with no position, so nothing drew it. If you have an older game where pieces vanished on the map, this is why, and it is now fixed.)

Filling a board at game start

Two setup verbs put pieces on a board. A placement names a component and, optionally, the cell it starts on; leave the cell off and a whole batch spreads one piece per cell. A deal does the same for cards coming off a deck — deal 12 into a 4×3 board and you get one per cell, or name the cells yourself to place them exactly.

Both need a board with cells to hand out. An open lattice mints its positions where pieces land and has no fixed set, so neither verb can fill one automatically.

How to edit in the Studio

Open your game → Layout tab and select the board zone. For square/hex grids, the Zone inspector exposes the grid dimensions, a Show grid lines checkbox, and a Pieces fill their cell checkbox; the fit overlay lets you drag the cell block to line up with a board image. For a graph grid, the graph inspector opens: toggle into Move, Add, or Connect mode to drag nodes onto their printed spots, drop new nodes, and click two nodes to link them. The same panel toggles nodesVisible, toggles Allow pieces anywhere on the board (freePlacement), and sets the default node size, with one-click “Fit nodes to box” and “Match box aspect” fixes for aligning the topology over a surface image.

Naming the spaces on a board with no art

A region is normally a semantic group: it lets setup and selections target “the far row” or “the sea hexes” without saying which cells those are. On a board with a surface image, that is all it does — the printed art already tells a player what each space is, so drawing the region on top would only cover the artwork.

A board with no surface image has nothing else to say it. There, each cell takes its region’s name as a small corner label and a faint tint, so a roll-and-move track reads as GeoGuessr, Chance, Beer Pong rather than as a grid of identical blank squares. A trailing “spaces” is trimmed on the cell itself (the full name is in the tooltip), since it repeats on every one.

This is a fallback, not a replacement. A cell with its own label or color in cells[] always wins, so anything you set by hand — or ask Pip for — stands. Reach for real cells when the spaces need names of their own rather than their group’s.

Adding and removing hexes

On a hex board the cell list is the board — a hex exists because cells[] has an entry for it. (This is the one thing the Regions section does not control: a region is a label over cells that already exist, so shortening its cell list renames nothing and removes nothing.)

The Grid card's Cells panel is where that list lives. Each hex is a chip: hover one to make it glow on the board, click its × to remove it. Tick Edit on board to work on the canvas instead — click a hex to remove it, and click any dashed outline to add a hex there. Dashed outlines ring the whole board, so the same gesture grows it outward. Removing a hex is not undoable; Reset is the way back.

A hex never leaves quietly. If a starting piece is placed on it, or it is the last cell of a region, the panel says so and waits for you to confirm — and when you do, that piece and that region go with the hex, so nothing is left pointing at a cell that no longer exists. Removing an empty hex just removes it.

To reshape a board wholesale, use Regenerate as hexagon: pick a radius (2 → 19 cells, the classic 3-4-5-4-3 island; 3 → 37, adding the sea ring) and rebuild. Hexes that survive keep their colour, label and region, and your existing regions are kept and trimmed rather than replaced.

One thing to expect: cell names like “NE · outer” are derived from where the hex sits in the board's rings, so trimming the outer ring renames the hexes that remain. Names you type yourself stay put.

Sign in to ask Pip about building games.
Sign in