
# Data Binding

`dataSource` binds a page or a component to a table. The records it resolves become available to every descendant through `$record.<field>` references.

```yaml
- type: data-table
  dataSource:
    table: tasks
    filter:
      - { field: status, operator: neq, value: archived }
    sort:
      - { field: created_at, direction: desc }
    pagination: { pageSize: 25, style: numbered }
```

## `dataSource` Properties

| Property         | Description                                                                         |
| ---------------- | ----------------------------------------------------------------------------------- |
| `table`          | **Required.** Table to bind to, validated against `app.tables`.                     |
| `fields`         | Specific fields to fetch. Omit to fetch all.                                        |
| `mode`           | `list` (default), `single`, or `search`.                                            |
| `filter`         | `{ field, operator, value }` conditions, combined with AND.                         |
| `sort`           | `{ field, direction }` rules applied in order — primary, then secondary.            |
| `pagination`     | `{ pageSize, style }`. `pageSize` is required when the block is present.            |
| `param`          | Route parameter to resolve the record from, in `single` mode.                       |
| `searchFields`   | Fields searched in `search` mode. At least one.                                     |
| `searchEngine`   | `client`, `fts`, `trigram`, or `hybrid`.                                            |
| `debounceMs`     | Delay before a search query fires.                                                  |
| `limit`          | Cap on the number of records returned.                                              |
| `targetId`       | Names this source so another component can bind to it.                              |
| `bindTo`         | Reads a source named by another component's `targetId` instead of fetching its own. |
| `sharedFilter`   | Filter contributed to the shared source referenced by `bindTo`.                     |
| `refreshMode`    | `none` (default), `poll`, or `realtime`.                                            |
| `pollIntervalMs` | Poll interval in milliseconds when `refreshMode: poll` — between 1000 and 300000.   |

A component may bind to a platform endpoint instead of a table with `dataSource: { system: { endpoint: … } }`, or to a named entry from the [system source catalog](/en/docs/system-sources).

## Filter Operators

| Operator     | Matches                                                    |
| ------------ | ---------------------------------------------------------- |
| `eq` / `neq` | Equal / not equal.                                         |
| `gt` / `gte` | Greater than / greater than or equal.                      |
| `lt` / `lte` | Less than / less than or equal.                            |
| `contains`   | Substring match.                                           |
| `in`         | Value is one of an array — used with `$currentUser` lists. |

Conditions combine with AND. There is no OR at this level; express alternatives as a [saved view](/en/docs/table-views) or a separate component.

## Single & Search Modes

`mode: single` resolves exactly one record, read from the route parameter named by `param` — the pattern behind [record detail routes](/en/docs/pages-routing#record-detail-routes).

`mode: search` filters across `searchFields` as the visitor types, throttled by `debounceMs` and capped by `limit`:

```yaml
- type: list
  dataSource:
    table: articles
    mode: search
    searchFields: [title, summary]
    searchEngine: fts
    debounceMs: 250
    limit: 20
```

## Pagination

| `style`    | Renders                                     |
| ---------- | ------------------------------------------- |
| `numbered` | Numbered page navigation.                   |
| `loadMore` | A Load More button appending the next page. |
| `infinite` | Automatic loading as the visitor scrolls.   |

## Reference Families

Component `content` and `props` values resolve four reference families at render time:

| Reference             | Resolves to                                                                   |
| --------------------- | ----------------------------------------------------------------------------- |
| `$record.<field>`     | A field of the current data-source record.                                    |
| `$vars.<key>`         | A page-scoped variable declared in the page's `vars`.                         |
| `$currentUser.<path>` | Session context — see below.                                                  |
| `$t:<key>`            | A translation key, falling back to the key itself when no translation exists. |

A page rendered from `markdown` additionally exposes `$frontmatter.*`.

## Current-User Scoping

`$currentUser` resolves per request during SSR and is never cached across users.

| Path                               | Value                                                                 |
| ---------------------------------- | --------------------------------------------------------------------- |
| `$currentUser.id`                  | The signed-in user's id.                                              |
| `$currentUser.email`               | Their email address.                                                  |
| `$currentUser.role`                | Their role name.                                                      |
| `$currentUser.isUnrestricted`      | `true` for a global admin, who bypasses assignment scoping.           |
| `$currentUser.assignments.<table>` | The record ids the user is assigned to in that table. Pair with `in`. |
| `$currentUser.activeAssignment`    | The tenant switcher's active scope, or `null`.                        |

```yaml
- type: data-table
  dataSource:
    table: projects
    filter:
      - { field: id, operator: in, value: '$currentUser.assignments.projects' }
```

:::callout
**A `$currentUser` filter makes the page authenticated.** Resolving one with no session answers `401 Unauthorized` — this is separate from the page `access` gate, which redirects or 404s instead. A `layout.sidebar` section that hits the same condition is dropped silently rather than failing the page.
:::

## Related Pages

- [Pages Overview](/en/docs/pages-overview) — the full page property table.
- [Data Components](/en/docs/data-components) — the components that consume a source.
- [System Sources](/en/docs/system-sources) — binding to platform endpoints by name.
- [Views](/en/docs/table-views) — saved filters and sorts.
- [Layouts, Sidebars & Access](/en/docs/pages-layouts-access) — the `access` gate.
