Architecture

Canvas layer model and ownership boundaries.

Canvas is organized as an isolated agent workspace topology:

@agent-html/react
  -> headless collaboration protocol and interaction events

agent-html/*
  -> agent operating context and reusable resources

agent-html/artifacts/*
  -> durable artifact composition and content

packages/cli/src/*
  -> Vite middleware dev host, guard, and stylesheet entrypoints

packages/cli/src/host/*
  -> sandbox host, inspector, and prompt bridge

packages/cli/src/host/styles/*
  -> host chrome implementation styles that consume Canvas tokens

Each layer owns one decision. The protocol marks stable regions and emits instrumented state changes. The agent-html workspace provides durable context agents can read and reuse. Artifacts compose those resources into UI. The CLI discovers, guards, serves, and routes artifacts through Vite middleware. The host observes and operates on rendered metadata.

Protocol

Artifact and Block are headless protocol markers.

They own metadata, anchors, and accessibility minimums. Artifact also owns the readable root container, with layout parameters configured by Canvas CSS tokens instead of artifact source props. Block is fully protocol-only: it accepts id, title, and children. It does not own width, spacing, colors, borders, radius, shadow, cards, panels, grid structure, or props passthrough.

@agent-html/react exports InteractionProvider, useArtifactInteraction, useEmitArtifactStateChange, useInstrumentedValueChange, and useInstrumentedCheckedChange. These helpers record local control state and dispatch agent-html:state-change events.

Resources

Canvas resources live under agent-html:

AGENTS.md
package.json
components.json
tsconfig.json
styles/index.css
styles/base.css
styles/materials/*
styles/layouts/index.css
styles/layouts/composition.css
styles/internal/*
theme/*
components/ui/*
components/*.tsx
hooks/*
lib/*
types/*
assets/*
public/*
artifacts/*
artifacts/*/data/*

Artifacts should consume these resources before adding local one-off helpers.

Composition

Artifacts decide block content layout explicitly:

<Artifact title="Project Brief">
  <Block id="summary" title="Summary">
    <Card>...</Card>
  </Block>
</Artifact>

Block marks an inspectable region. It is not a card, panel, or section style. Do not put layout classes on Block; put layout inside the block content.

Host

The host renders artifacts, discovers blocks, displays guard issues, overlays block prompt actions, handles floating prompts, applies theme presets, and loads Canvas stylesheets. Host controls use Canvas UI primitives and theme resources through #agent-html-playground/components/ui/* and #agent-html-playground/theme/*; the host must not define artifact visual language.

Host workbench code is a consumer and composer of runtime pipelines. Its owner map is:

host/api
  -> dev-server API contract

host/artifact
  -> artifact registry consumption and artifact module runtime

host/overlay
  -> rendered Block metadata measurement and prompt anchors

host/prompt
  -> floating prompt host state, drafts, and block message lifecycle

host/pipeline
  -> Codex/example backend adapters and prompt formatting calls

host/interaction
  -> artifact state-change event snapshots for prompt context

host/preferences
  -> local host preference persistence

host/theme
  -> host theme mode, preset layout, draft preview, and runtime variables

host/navigation
  -> sidebar command surface

ReactCanvasHostWorkbench composes those owners. It should not directly own dev-server route semantics, workspace validation, prompt backend execution, message store publishing, theme side effects, artifact registry refresh rules, or Canvas protocol semantics.

Pipeline Map

This page is the authoritative Canvas pipeline map. The shared block prompt model is:

artifactEntry + blockId + implementationPath + interactionSnapshot
PipelineOwnerInputOutputForbidden dependenciesPrimary tests
Workspace sourceagent-htmlartifact entries, split block files, local resourcesportable source workspacegenerated bundles, lockfiles, vendored installsworkspace-contract.test.mjs
Workspace file/path helpersreact-canvas/paths.mjs + react-canvas/workspace-file.mjsroot path or source file pathPOSIX workspace path or text sourcegeneric filesystem abstraction, mutation APIs, host statepipeline-ownership-contract.test.mjs, workspace-contract.test.mjs
Artifact discoveryreact-canvas/paths.mjsagent-html/artifacts/*.artifact.tsxartifact entry file pathsapp shell, runtime parser, host UIdev-host.test.mjs, pipeline-ownership-contract.test.mjs
Artifact entry protocol guardreact-canvas/guard.mjsartifact entry sourceissues scoped as artifact-entry-protocollayout or style props on Artifact or Blockguard.test.mjs
Block implementation source guardreact-canvas/guard.mjsagent-html/artifacts/**/*.block.tsxissues scoped as block-implementation-sourceraw visual classes, native primitive bypassesguard.test.mjs, style-ownership-contract.test.mjs
Workspace boundary guardreact-canvas/guard.mjsartifact and block source importsissues scoped as workspace-boundaryapp imports, old runtime imports, public-file importsguard.test.mjs, workspace-contract.test.mjs, architecture-boundaries.test.mjs
Dependency resolutiondev-server/vite.mjssource import specifierCLI-provided runtime moduleagent-html/node_modules, source-owned runtime installsruntime-resolution-contract.test.mjs
Module transform and renderVite middleware + host artifact runtimeartifact entry file pathmounted artifact DOM with HMR-capable module graphapp shell, old runtime render APIsdev-host.test.mjs, artifact-runtime.test.ts
Public/static asset servingdev-server/routes.mjs + host/api URL helperspublic asset path or proxied font URLserved asset response or host URLdirect Host endpoint strings outside host/apidev-host.test.mjs, routes.test.mjs, api.test.ts, architecture-boundaries.test.mjs
Artifact registry consumptionhost/artifact/use-artifact-registry.tsartifact registry response and pending artifact pathactive artifact, guard issues, registry refresh operationsdev-server route implementation, workspace validationapp.test.tsx, pipeline-ownership-contract.test.mjs
Block overlaypackages/react + host overlayrendered data-agent-html-block-* metadatahover highlight and prompt targetartifact source mutation, host APIs in artifactsblock-overlay.test.ts, index.test.tsx
Block implementation lookupdev server + host APIartifactEntry, blockIdimplementationPathselected source payloads, implementation source payloadsblock-implementation.test.mjs, dev-host.test.mjs
Block promptreact-canvas/prompt.mjsartifactEntry, blockId, optional implementationPath, host interactionSnapshotminimal prompt packetselected source payloads, implementation source payloadsprompt.test.mjs
Create artifacthost/pipeline + react-canvas/prompt.mjscreate request and generated artifact file pathCodex/example turn requestdev-server implementation, artifact source mutation in Hostpipeline.test.ts, app.test.tsx
Guard fixhost/pipeline + react-canvas/prompt.mjsguard errors for one artifactCodex/example turn requestwarnings-only prompt payloads, host UI state payloadspipeline.test.ts, prompt.test.mjs
Interaction statepackages/react event protocol + host storeartifact-local control changeshost prompt interaction snapshotfilesystem, shell, MCP, privileged host APIs in artifact codeindex.test.tsx, interaction-store.test.ts, prompt.test.mjs
Preferences persistencehost/preferenceslocal host preference statepersisted host preference patchartifact source state, dev-server statecanvas-host-preferences.test.ts, use-canvas-host-preferences.test.ts
CSS/themeagent-html/styles + package host styles + host theme ownerCSS tokens, content classes, theme presets, host chrome CSSstylesheet and runtime variablesartifact-owned root chrome, sidebar token overrides, host chrome implementation in artifact contextstyle-ownership-contract.test.mjs, style-resource-contract.test.mjs, theme-preset.test.ts, theme-layout.test.ts

Dev server routes are orchestration only. They are grouped into explicit runtime adapter pipelines:

host-shell
runtime-module
styles-and-assets
public-asset
artifact-registry-and-guard-report
artifact-source-mutation
block-lookup
codex-bridge

The dev server owns server lifecycle, route dispatch, Vite runtime creation, dependency supply, and asset serving. Host shell, artifact module, stylesheet, public asset, artifact registry and guard report, artifact mutation, block lookup, and Codex bridge requests enter through those named pipelines. The dev server delegates host and artifact module transforms to Vite.

It does not own protocol semantics, host interaction state, artifact visual language, or block prompt meaning. Those remain owned by @agent-html/react, the host interaction store, Canvas styles/resources, and the prompt pipeline.

Boundary Governance

Canvas boundary checks follow the layer topology:

packages/react
  -> protocol only; no host, workspace, docs, app, or archive imports

packages/cli/src/react-canvas
  -> discovery, guard, prompt, and workspace path orchestration
  -> no host UI, artifact source, Canvas UI, theme, docs, app, or archive imports

packages/cli/src/host
  -> host inspector chrome and pipeline calls
  -> Canvas UI/theme only through #agent-html-playground/components/ui/* and
     #agent-html-playground/theme/*

agent-html/artifacts
  -> artifact source
  -> no host, app, docs, archive, public-file imports, or internal style imports

packages/cli/src/react-canvas/architecture-boundaries.test.mjs owns the topology checks. Use it as the executable boundary matrix before adding new guard behavior. Workspace source constraints live in workspace-contract.test.mjs, package/runtime ownership lives in package-runtime-contract.test.mjs, pipeline ownership lives in pipeline-ownership-contract.test.mjs, archive separation lives in archive-runtime-boundary-contract.test.mjs, and style ownership lives in style-ownership-contract.test.mjs plus style-resource-contract.test.mjs.

style-ownership-contract.test.mjs also records the current fixed-format artifact layout exceptions for media, map, and carousel blocks. Those exceptions are not a new styling surface; new artifact code should prefer Canvas public composition classes and shrink that list when equivalent composition classes exist.

Dependency Resolution

agent-html/package.json records source dependency metadata for local Canvas resources. It is not an installation target. The CLI package provides runtime dependencies. The dev host is the only mapping layer between source imports and runtime modules: it resolves workspace imports through CLI-owned dependencies, exact package aliases, Vite import-entry resolution, and explicit optimizeDeps.

React and React DOM stay pinned through dedicated aliases so the host and artifacts share one renderer instance. Named exports used by workspace source must be present on the resolved runtime entries; this catches ESM/CJS mismatch before browser module loading fails.

The dependency contract is executable: workspace-contract.test.mjs checks source-only workspace files, source metadata, and forbidden vendored installs. package-runtime-contract.test.mjs checks CLI runtime ownership. runtime-resolution-contract.test.mjs checks Vite dependency aliases, ESM import entries, runtime exports, React singleton resolution, explicit optimizeDeps, and filesystem allow-list boundaries. routes.test.mjs checks route pipeline ownership. dev-host.test.mjs checks artifact rendering and fresh-project startup through the real dev host.

Guard Scopes

Canvas guard reports one issue list with explicit scopes:

  • artifact-entry-protocol: validates the artifact entry, including default export, Artifact, Block, stable blockId, and protocol-only marker props.
  • block-implementation-source: validates split block implementation source for source-level visual and primitive boundaries.
  • workspace-boundary: validates imports and workspace access boundaries across artifact entries and block implementations.

The dev host treats all guard issues as preview feedback, but the scope names identify which pipeline owns the failure.

Interaction Source Of Truth

@agent-html/react owns portable instrumentation and the event protocol. Its artifact-local snapshot helps controls compose locally, but it is not the prompt context source of truth.

The host interaction store owns prompt context. It records agent-html:state-change events by artifactEntry + blockId, compacts them, and passes the resulting interactionSnapshot into the block prompt pipeline.

On this page