> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frogbot.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Collection board

> Configure a draggable board for a collection.

Add a board entry to `admin.views` to show documents as cards grouped into columns. Include a list entry when users should be able to switch between table and board layouts.

`admin.views` uses the exported `CollectionView` union. See the complete [Collection views reference](https://docs.frogbot.ai/configuration/collections.md#collection-views) or configure a [Collection calendar](https://docs.frogbot.ai/admin/collection-calendar.md).

## Board properties

| Property | Type | Required / default | Behavior |
| - | - | - | - |
| `type` | `'board'` | Yes | Selects the board layout. |
| `slug` | `string` | No; defaults to `'board'` | Unique normalized route and preference key. The first view uses the collection's root route. |
| `label` | `string` | No; defaults to `'Board'` | Label shown in the view switcher. |
| `groupBy` | `string` | No | Dot path to the select or single relationship field that determines each card's column. |
| `defaultFields` | `string[]` | No | Dot paths to the fields rendered on each card, in display order. |
| `cover` | `string` | No | Dot path to an upload field rendered as the card's cover image. |
| `filter` | `Where \| ({ req }) => Where \| Promise<Where>` | No | Invisible base filter applied to every board query. |
| `defaultSort` | `Sort` (`string \| string[]`) | No | Initial card order within columns. Prefix a field with `-` for descending order. |
| `searchableFields` | `string[]` | No | Adds fields to normal search behavior; `useAsTitle` remains included. |
| `pagination` | `ViewPagination` | No; `defaultLimit: 50` | Sets the documents fetched per column. Each column lazy-loads additional pages and virtualizes rendered cards. `limits` only drives list page-size choices. |
| `access` | `({ req }) => boolean \| Promise<boolean>` | No; collection access | Controls whether the current user can open the board without replacing collection operation access. |
| `components` | `ViewComponents & BoardComponents` | No | Configures shared view slots and board components. |

## Board components

| Property | Type | Required / default | Behavior |
| - | - | - | - |
| `actions` | `FrogBotComponent[]` | No; `[]` | Renders in the page header, top right. |
| `toolbar` | `FrogBotComponent[]` | No; `[]` | Renders in the board's view controls, before Filters. Below the small breakpoint it moves into a right-aligned row under the toolbar. |
| `menuItems` | `FrogBotComponent[]` | No; `[]` | Adds entries to the board menu. |
| `beforeView` | `FrogBotComponent[]` | No; `[]` | Renders inside the collection shell before the board body. |
| `afterView` | `FrogBotComponent[]` | No; `[]` | Renders inside the collection shell after the board body. |
| `beforeColumns` | `FrogBotComponent[]` | No; `[]` | Renders before the columns. |
| `afterColumns` | `FrogBotComponent[]` | No; `[]` | Renders after the columns. |
| `ColumnHeader` | `FrogBotComponent` | No; built-in header | Replaces each column header. See [Column headers](#column-headers). |
| `Card` | `FrogBotComponent` | No; built-in card | Replaces each card and receives the document as its `row` prop. |

```ts theme={"theme":"tokyo-night"}
export const Tasks: CollectionConfig = {
  slug: 'tasks',
  admin: {
    views: [
      {
        type: 'list',
        defaultFields: ['title', 'stage', 'assignee', 'dueDate'],
      },
      {
        type: 'board',
        slug: 'workflow',
        label: 'Workflow',
        groupBy: 'stage',
        defaultFields: ['title', 'assignee', 'dueDate'],
      },
    ],
  },
  fields: [
    { name: 'title', type: 'text' },
    {
      name: 'stage',
      type: 'select',
      options: ['Backlog', 'Review', 'Done'],
    },
    { name: 'assignee', type: 'relationship', relationTo: 'users' },
    { name: 'dueDate', type: 'date' },
  ],
}
```

The group field must be a single select or relationship field. Select option order controls column order. Documents without a value appear in **Uncategorized**.

Dragging a card performs a normal collection update, including access checks, validation, and hooks. A rejected update restores the card to its original column and displays the error.

Nested fields use dot paths such as `workflow.stage` and `details.dueDate`.

Board views use `pagination.defaultLimit` for each column, defaulting to 50. Columns lazy-load subsequent pages and virtualize their cards. `pagination.limits` applies only to list page-size controls. Omitting `admin.views` creates one default list view without a switcher, using FrogBot's normal list pagination defaults.

## Column headers

Each column header shows the column's label and the number of cards loaded in it. When the group field is a select or radio field with [option colors](https://docs.frogbot.ai/fields/select.md#option-colors), each option's header shows its label as a coloured pill, and options without a colour show as `gray`. **Uncategorized** always keeps a plain label.

A `ColumnHeader` component replaces the whole header and receives these props:

| Prop | Type | Behavior |
| - | - | - |
| `column.key` | `string` | Stable key for the column. |
| `column.label` | `string` | Label shown in the header, such as the option label or the related document's title. **Uncategorized** for documents without a value. |
| `column.value` | `unknown` | Stored group value for the column. `undefined` for **Uncategorized**. |
| `column.color` | `OptionColor \| undefined` | The option's colour. Set only when the group field has option colors, and never for **Uncategorized**. |
| `count` | `number` | Cards loaded in the column so far. |

Use `OptionPill` from `@frogbotai/ui` to draw the same pill as the built-in header. It accepts these props:

| Prop | Type | Required / default | Behavior |
| - | - | - | - |
| `color` | `OptionColor` | Yes | One of the seven option colours. |
| `children` | `ReactNode` | No | Pill content. |
| `className` | `string` | No | Added after the pill's own classes. |
| Other `span` props | `ComponentProps<'span'>` | No | Passed to the rendered `span`. |

```tsx theme={"theme":"tokyo-night"}
'use client'

import { OptionPill } from '@frogbotai/ui'
import type { OptionColor } from 'frogbot'

type StageHeaderProps = {
  column: { color?: OptionColor; key: string; label: string; value: unknown }
  count: number
}

export function StageHeader({ column, count }: StageHeaderProps) {
  return (
    <>
      {column.color ? <OptionPill color={column.color}>{column.label}</OptionPill> : <strong>{column.label}</strong>}
      <span>{count === 1 ? '1 task' : `${count} tasks`}</span>
    </>
  )
}
```

```ts theme={"theme":"tokyo-night"}
{
  type: 'board',
  groupBy: 'stage',
  components: { ColumnHeader: '/components/StageHeader#StageHeader' },
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.