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

# Custom components

> How components your agent writes run in a sandbox, which npm packages they may use, how several components share state, and how they reach live data and canvas tools.

When the building blocks are not enough, your agent can write its own React component in TSX. CanvasView checks and compiles it when the canvas is created or changed, then runs it in a sandbox on every viewer's page.

This page explains how custom components behave. Your agent's exact rules, props and hooks are in the generated [kit reference](https://app.canvasview.dev/agents/kit.md), and the plugin's `build-component` and `build-app` skills teach it to use them.

## What a component is

A component is a canvas node with `kind: "component"`, a TSX `source`, and optional `data` and `title`. It exports a default React component that receives `{ data, theme, size }`. `theme` is `light` or `dark` and follows the viewer. The title names the component on the canvas and on its tab. Without one it is labelled **Made by an agent**.

A component may import from `react`, from `@canvasview/kit`, and from npm packages it declares. The kit provides the same building blocks the catalog uses, plus hooks:

| Hook | What it does |
| - | - |
| `useDraft` | Fills fields in the canvas's answer panel. |
| `useSubmit` | Asks to submit an answer. CanvasView shows the values and sends them only after the person confirms. |
| `useSharedState` | A value every viewer sees live, which survives reloads. Components that use the same key share it. |
| `useSharedGroup` | One value per person, for things several people write at once, such as votes. |
| `useGroupMode` | Lets several people use the component at once. See [One person at a time](#one-person-at-a-time). |
| `useData`, `fetchData` | Read from or write to a data source you approved. See [Live data](#live-data). |
| `useRoute`, `RouteLink` | Show and link between the component's own pages. See [Pages](#pages). |
| `useTool`, `canvas.tools` | Call one of the canvas's tools. See [Canvas tools](#canvas-tools). |

CanvasView checks every component before it creates or changes a canvas. A component that fails to compile, or imports something it may not, is refused with a message that names the problem, and nothing is charged.

## The sandbox

Each component runs in its own sandboxed frame:

* **No network.** The frame cannot fetch, open connections, load scripts or images from a URL, or submit forms. Only code CanvasView placed in the frame can run.
* **No access to the page.** The frame has its own opaque origin. It cannot read the viewer's cookies, the CanvasView session or the page around it.
* **No pop-ups.** Links inside a custom component do not open. Links in building blocks do.
* **Unresponsive frames are removed.** If a component stops answering, CanvasView removes its frame and the rest of the canvas keeps working.

A component talks to the page only through CanvasView's messages, such as shared state, data requests, tool calls and answers. Each write is tagged with the component that made it, outside the sandbox, so code in one component cannot write as another.

> [!WARNING]
>
> Components on a canvas are written by an agent. The answer panel on a canvas with custom components reminds viewers never to enter passwords or access keys.

Agents are told never to build a sign-in screen or a field that asks for a password, API key, card number or other secret. CanvasView never asks people to sign in on a canvas, so a sign-in box there looks like phishing. Outside services are reached through a [data source](https://docs.canvasview.dev/account/data-sources.md) instead.

## One person at a time

Each custom component is controlled by one person at a time. While someone else uses it, the component shows live state but takes no input, outlined in that person's presence colour. A component built for many people at once, such as a poll or a board, opts out of this with `useGroupMode` and writes one value per person.

## npm packages

A component node can declare npm packages in `packages`, mapping each name to an exact version:

```json theme={null}
{ "packages": { "three": "0.170.0" } }
```

CanvasView enforces these rules:

* At most 12 packages per component.
* An exact published version, such as `1.2.3`. Ranges, tags, URLs, git specs and aliases are refused.
* The version must be at least 3 days old, except for `@ui-sdk` packages.
* Deprecated versions, versions with a malware advisory, and packages CanvasView blocks are refused.
* `react`, `react-dom` and `@canvasview/kit` are provided by the sandbox. Do not declare them. Packages share the sandbox's React 19.
* What one package pulls in is limited to 5 MB, and everything one component loads to 3 MB.

CanvasView bundles each package version on its own servers and stores the result for your organization. Viewers receive only that stored copy. Nothing is fetched from a public CDN when a person opens the canvas, and no install script runs.

## Apps of several components

Several components can share state to work as one app. For example, the `contract-app` example has an inputs component, a calculation that writes results, and a chart that reads them.

An optional app contract makes those rules explicit. It says which shared-state keys the canvas uses, the shape of each value, which components may write each key, and what each component is for. With a contract, the canvas refuses a write to an undeclared key, a value that does not fit, or a write from a component that is not a writer. The agent may always write any declared key. Without a contract, shared state is open to every component.

## Live data

The sandbox has no network, so a component reaches outside data only through a [data source](https://docs.canvasview.dev/account/data-sources.md) you approved:

1. The agent lists the source's name in the canvas's `dataSources`.
2. The component calls `useData(source, { path, query })` to read, or `fetchData(source, { path, method, body })` for one request, such as a write when someone presses a button.
3. CanvasView checks the call, adds the source's secret headers and calls the service.
4. The component gets the status, content type and body.

A component never sees the secret headers. Writes work on active canvases only, and only with methods you allowed.

When the agent refreshes a component's data with a data-only `patch_canvas`, open components receive the new data without reloading. That patch is free.

## Pages

A component can have up to 20 pages of its own, declared as `routes` on its node, such as `/` and `/customers`. Each page has a title for CanvasView's menus and its own address, `/c/<canvas>/<component>/<path>`. The address follows the page and **Back** works. The component reads the open page with `useRoute` and links between pages with `RouteLink`.

## Canvas tools

A tool is code that the canvas runs for its components and agents, such as a lookup against a data source. Your agent writes it and publishes it to the canvas with `publish_tools`. A tool has a manifest that says what it takes, what it returns and which data sources it may call, plus recorded cases it must pass before it goes live. A refused publish changes nothing.

* Components call a tool with `useTool` or `canvas.tools.<name>(input)`. A tool can also poll or stream, writing shared state for everyone.
* A tool reaches only the data sources its manifest names, through CanvasView, which attaches the secrets. The tool's code never sees them.
* A canvas holds up to 20 tools. Each call is logged, with the source and credential names it used, never their values.
* Each canvas has a Git repository holding its spec, components and tools. Each version of the canvas is a commit. Your agent can clone and push to it with a short-lived token.
* When a tool keeps failing, your organization gets a [notification](https://docs.canvasview.dev/account/notifications.md).

Running tools is free for now. The tools are listed in [tools.md](https://app.canvasview.dev/agents/tools.md).

## Reuse

Agents can save a component to your organization's library and reuse it by name. See [Templates and saved components](https://docs.canvasview.dev/people/templates-and-saved-components.md).


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