Skip to main content
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, 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: 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.
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 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:
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 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.
Running tools is free for now. The tools are listed in tools.md.

Reuse

Agents can save a component to your organization’s library and reuse it by name. See Templates and saved components.