Tecto docs
tectoapp.io

Boards, columns and lanes

A board lives in a collection. Collections are how boards are grouped — "Product", "Client work", "Internal" — and a board sits at a collection's root, never underneath another board.

A board is three things at once, and it is worth separating them:

  1. A grid — its columns and lanes.
  2. A document — a body you can write in, above the grid.
  3. A set of cards — which are pages, and are their own page.

The grid

Columns are the stages: To do, Doing, Done. Each has a label and, if you want one, an icon. A column has no colour, and that is deliberate: it would be a second mark beside the icon, and the weaker of the two — a colour has to be learned per board, a glyph does not.

Lanes are the horizontal split: by team, by workstream, by client. A lane has a label and nothing else — the columns carry the mark, and marking both makes a board that shouts in two directions at once.

Both are just lists on the board. Reordering columns is reordering the list. Either can be folded away, and so can the implicit row of cards in no lane; that state sits on the board, so a column folds for everyone who opens it.

curl -X PATCH "$BASE/api/v1/workspaces/$WS/boards/$BOARD" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "columns": [
      { "id": "…uuid…", "label": "To do"  },
      { "id": "…uuid…", "label": "Doing"  },
      { "id": "…uuid…", "label": "Done" }
    ]
  }'

Three properties of that call are load-bearing:

  • The list is replaced whole, not merged. Send every column you want to keep. There is no "add one column" call, because two clients each adding one column to a partial list is how a board silently loses a stage.
  • You mint the ids. A column's id is yours and board-local, which is what lets you rename "Doing" to "In progress" without touching a single card: the cards point at the id, not at the label.
  • Deleting a column does not move its cards. They keep the id they had, and the grouped read reports them under it. Nothing is lost, and nothing is silently reassigned to a stage you did not choose — but a board in that state has cards you cannot see in the grid until you re-add the column or move them.

A new board starts with no columns and no lanes. The server has no opinion about what your first three columns should be called; whatever creates the board decides.

The board's body

A board carries a document of its own, above the grid — the same editor a page has. It is for the thing a column heading cannot say: what this board is for, how it is run, what "Done" means here.

Cards can be embedded into that body, so a paragraph can point at the card it is about and the card stays a card.

Comments on the board's body are not built. Comments on cards are.

Reading a board

A board is read in one request, grouped:

GET /api/v1/workspaces/{workspaceId}/boards/{boardId}/cards

The response is groups of (column × lane), each with a window of cards, a cursor of its own and a total count. That shape is the point: a board with ten thousand cards has to draw the top of every column without reading every card, and paginating a board as one flat list cannot do that. windowSize sets how many cards per group.

Two things a reader should expect:

  • An empty board has no groups, not one empty group per column. Groups come from cards.
  • There is a group with no column — the cards that have never been placed. A row added to the board's backing database through the generic row API arrives there. Without it those cards would exist and be unreachable.

Board reads are viewer-dependent. A card whose page you may not read is left out entirely rather than shown as a stub, so counts and cursors differ per person. That is the same rule the rest of the platform follows: "you cannot see it" and "it is not there" look alike on purpose.

Permissions

  • Listing and reading a board needs read on its collection.
  • Creating one needs edit on the collection.
  • Changing a board — its title, icon, columns, lanes — needs edit on the board.
  • Deleting one needs full. It goes to the trash, and takes its backing database out of reach with it.

Moving a card is governed by the board, not by the card's page. Someone with edit on the board can drag a card whose page they cannot read — they are changing where a card sits, not what it says. Opening that card still needs read on the page, and writing in it still needs edit.

That split is what makes a board usable in a team where not everything is readable by everyone.

A board is not a database view

If you know typed databases with saved views: a board is not one of those with a kanban layout bolted on. It is its own kind of document, sibling to a page, with its own body and its own configuration. Behind its cards sits a database the board creates and manages for itself, but the grid belongs to the board, not to a view.

What a board cannot do

  • No WIP limits. Nothing counts the cards in a column against a maximum.
  • No filters and no sorting. A board is always in board order — the order cards were placed in. There is no "show only mine", no "sort by priority".
  • No templates, no automations, no card covers, no public share link.
  • No import from another tool.

Every one of those is a decision on record rather than an oversight, and none of them is close.