DocsLayout & seats

Layout

A zone says what a region means and how its contents behave — but not where it is. That lives in layout. The layout block holds two things: the seats around the table, and a placement for every zone — its position and size on the felt.

Layout is deliberately kept separate from the zone definitions. Zones carry meaning; layout carries geometry. Because they’re separate, your hand-tuned positions survive regeneration — re-running the pipeline can rewrite a zone’s role or contents without throwing away where you placed it.

Every coordinate here is in abstract table units, with the table origin at its centre. Only the ratios between things matter — pixel scaling happens at render time.

The table

Every game is laid out on the same table. There is no per-game size or shape to pick: the felt fills the whole window, and the default view frames a fixed 1500 × 1000 area centred on the origin. Keep anything players need at a glance — hands, decks, the board — inside that rectangle. You can place things beyond it (the felt keeps going, and players can zoom out to reach them), but nothing will point them there.

The table also takes an optional surfaceAsset — a felt or board image painted across it — and an optional viewMode controlling how the scene orients for each player: fixed (default when omitted) locks the board upright for all players; seated rotates the scene so the viewer's seat faces the near edge — use it for directional board games where territory or orientation matters.

What a placement holds

Each zone has exactly one entry in layout.zones, keyed by zone id:

FieldTypeMeaning
spacetable | seatLocaltable = absolute table coordinates; seatLocal = relative to a seat, with one copy instantiated per seat, rotated to that seat
x / ynumber (table units)Position of the zone box (origin = table centre)
w / hnumber (table units)Zone box width and height (both positive)
rotationnumber .optional()Box rotation in degrees
layernumber .optional()Draw order when zones overlap
fitContentsboolean .optional()Scale contents to fill the box. Default lets the renderer pick: card zones fit, piece/dice/token trays don’t. Set true for a single-component zone you want to resize by resizing the box
lockedboolean .optional()Designer-only: the editor ignores the box’s own click/drag (handy for a big background board) — contents stay interactive; ignored at runtime
traySpanCols / traySpanRowsint ≥1 .optional()Tray zones only — when a zone lives in the bottom hand tray or right supply tray, its zones render as a grid of uniform square tiles (up to 4 per line). These let one zone span multiple columns / rows of that tile grid (a colspan / rowspan). The cap is asymmetric: the cross axis stays ≤4 per line — columns for the supply tray, rows for the hand tray — while the main axis is unbounded, so a supply tile can be many rows tall and a hand-of-cards tile many columns wide to fill and scroll the tray. Absent ⇒ an automatic tile box sized from what the zone holds — a fanned hand fills the tray’s height and spreads a few cards wide, a deck fills the height at one card’s width, a pile of pieces takes half. Set them per axis: pinning Columns leaves Rows automatic. Ignored for table zones, and the ≤4 cap is applied at render to whichever axis is that tray’s cross axis
bySeatrecord .optional()seatLocal zones only: per-seat geometry overrides keyed by seat index. A seat with no entry uses the base geometry, so the zone stays symmetric until you reposition one seat

How to edit in the Studio

Open your game → Layout tab. The table is drawn to scale; drag a zone to move it, drag its handles to resize, and use the Zone inspector to set rotation, layer, fitContents, and lock. Switching a zone to seatLocal space mirrors it to every seat at once; nudging one seat’s copy writes a bySeat override for just that seat. The Table inspector sets the surface shape, size, and image. For a full tour of the canvas, panels, and gestures, see the Layout Editor.

Arranging several zones

The editor snaps, aligns, and matches zones for you — marquee-select a group, then align, distribute, or Match their sizes. See arranging zones on the felt for the full gesture set.

Already have a set of zones that drifted out of line — a tableau of slots, a row of supply piles? Ask Pip to arrange or even out them: it reads where each zone currently sits, works out the tidy positions (lining up rows and columns, evening the gaps), and proposes the moves (positions only — sizes stay as you set them), which you review and Save like any edit.

Pip can also add pieces from the component library“add four red meeples to the supply”, “give me a d20” — so a missing piece takes one sentence rather than a trip to the Components tab. Ready-drawn catalogue objects need no uploaded art, which is why Pip can author them at all: there is no image id for it to guess at. Naming the zone in the same breath places them; leaving it out still creates the piece, ready for you to place.

Deleting a zone or component

Zones and components are referenced all over a game — a setup placement, a deck’s member list, a table-menu action, a setup step’s destination. When you delete one, Save clears the pointers that were left behind and tells you what it cleaned up, so a delete never leaves you unable to save. If a save is genuinely rejected, the message names the place to fix it — "Setup step 2", "Zone “Player Hand”" — rather than a raw field path.

Sign in to ask Pip about building games.
Sign in