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

# Surfaces

> AI-generated HTML pages hosted by Tokenrip, bridged to your data through a stable SDK

# Surfaces

A **Surface** is an AI-generated HTML page hosted by Tokenrip at `https://tokenrip.com/x/:publicId`. An agent writes a single self-contained HTML file; Tokenrip hosts it, versions it, validates it, and bridges it to live Tokenrip data through the injected `window.tokenrip` SDK.

Surfaces are the way an agent turns its work into a UI the operator can actually use — a review dashboard, a triage queue, an editor — without standing up a separate frontend project.

<Note>
  **Owner-only in v1.** The operator who owns the Surface is the only viewer. Surfaces are not shareable URLs yet. See [v1.5+ roadmap](#v15-roadmap) below.
</Note>

## The contract

Surfaces work because the agent never talks to `/v0` directly. Instead, every read and write goes through `window.tokenrip.*`, which is the public, stable contract:

* `window.tokenrip.surface.info()` — frozen metadata snapshot (publicId, revisionId, runtime, viewer, bindings).
* `window.tokenrip.tables.rows / patch / append` — read and mutate `mount_table` bindings.
* `window.tokenrip.artifacts.read / saveVersion` — read and version `artifact` bindings.

The HTTP routes underneath the SDK are internal implementation. Generated code that calls them directly is non-compliant — the validator flags it as `raw_v0_detected` and it may break on the next internal change.

For the full SDK reference (every method, every error shape, code examples), agents should read the in-repo teaching doc: **[https://tokenrip.com/for-ai/surfaces.md](https://tokenrip.com/for-ai/surfaces.md)**.

## Bindings

A Surface declares **binding keys** at publish time. Each key maps to either a mounted-agent table or a text artifact, with explicit permissions:

| Kind          | Source                                                 | Permissions                              |
| ------------- | ------------------------------------------------------ | ---------------------------------------- |
| `mount_table` | A table on a mounted agent                             | `rows:read`, `rows:patch`, `rows:append` |
| `artifact`    | A text artifact (markdown / html / code / text / json) | `read`, `version:create`                 |

Inside the generated HTML the agent references the binding *key*, never the underlying mount or artifact UUID:

```js theme={null}
const { rows } = await window.tokenrip.tables.rows('signals', { limit: 50 });
await window.tokenrip.tables.patch('signals', rowId, { status: 'approved' });
```

This is what lets Tokenrip swap internal routing (v1 REST bridge → v1.5 scoped runtime broker) without breaking deployed Surfaces.

## How an agent builds a Surface

<Steps>
  <Step title="Inspect">
    Call `inspect_mount(mountId)` for a mounted-agent workflow, or `inspect_artifact(publicId)` for a single-artifact editor. The response returns schemas, up to 5 sample rows, a `recommendedBinding`, and pasteable SDK example snippets.
  </Step>

  <Step title="Generate">
    Write a single-file HTML page. React via Babel-in-browser is the smooth path. Vanilla DOM works too. Only CDNs on the v1 allowlist are permitted.
  </Step>

  <Step title="Publish">
    Call `publish_surface({ title, htmlContent, bindings })`. Tokenrip persists the Surface as a draft and auto-runs Playwright validation.
  </Step>

  <Step title="Iterate">
    If validation reports errors (console errors, blocked writes, accessibility regressions), call `update_surface(publicId, { htmlContent })`. Each update auto-revalidates.
  </Step>

  <Step title="Hand off">
    Present the draft URL to the operator: "Review it, tell me when to promote." Surfaces stay in draft until the operator confirms.
  </Step>

  <Step title="Promote">
    On confirmation, call `promote_surface(publicId)`. The Surface goes live at `/x/:publicId`.
  </Step>
</Steps>

## Validation pipeline

Every publish and update runs a headless Playwright pass in a sandboxed Chromium. The runner:

* Loads the Surface at production-equivalent desktop and mobile viewports.
* Captures console + network errors and accessibility findings.
* Records all SDK calls + telemetry events.
* **Blocks all mutating SDK calls** — `tables.patch / append` and `artifacts.saveVersion` reject with `validation_blocked`. Generated UIs are expected to detect `runtime === 'validation'` from `surface.info()` and degrade gracefully (e.g. show a "Validation mode — writes blocked" banner instead of an error toast).
* Detects raw `/v0` calls and records them as `raw_v0_detected` events.

The validation summary is attached to the create / update response. If `errorCount > 0`, the agent fixes the HTML and re-publishes before asking the operator to promote.

## Revisions

Every `publish_surface` and `update_surface` creates a new revision. The current revision is the live one; all prior revisions are preserved. The operator can list revisions and restore an older one via `restore_surface_revision` — restore *copies* the source into a new active revision (the source is never mutated), then re-runs validation.

## Imprint surfaces

An agent imprint can **ship a starter Surface** so everyone who mounts it inherits the UI — the way an imprint ships memory tables or themes. The imprint declares a `surfaces[]` entry in its manifest; when someone mounts the imprint, each template is **cloned** into a real Surface on their mount, with its bindings re-targeted to *their* concrete tables and artifacts. Cloning is a one-time snapshot, so the mounter can edit, repoint, or delete their copy without the author's later edits disturbing it.

You don't author a template by hand. You build and validate a Surface the normal way on a mount of **your own** imprint, then promote it:

```
promote_surface_to_imprint(publicId, { alias: "signals-board", default: true })
```

This is the inverse of cloning. It derives **alias** bindings from your surface's concrete bindings (every bound table/artifact must already be declared in the manifest, else `SURFACE_BINDING_NOT_TEMPLATABLE`), snapshots the HTML into a starter artifact, and writes the `surfaces[]` entry. It's a draft manifest edit — publish the imprint to ship it. At most one template can be the imprint's `default`.

Each materialized surface remembers where it came from (`sourceTemplateAlias`), so the operator dashboard distinguishes three kinds: **template-derived** (cloned from an imprint), **mount** (built ad-hoc on a deployment), and **standalone** (no agent lineage). Repoint which surface a mount features by default with `set_default_surface(publicId)`.

## v1.5+ roadmap

The hybrid v1 deliberately keeps surface area small. Items deferred to v1.5 and beyond:

* **Scoped runtime broker** — replace the REST-bridge internals with per-Surface broker endpoints. Generated Surfaces keep working because the SDK contract stays stable.
* **Connectors** — `window.tokenrip.connectors.call(key, args)` for first-class external integrations (Gmail, Slack, Linear). Tokenrip-native confirmation for mutating calls; secrets stay server-side.
* **Cross-account sharing** — Surfaces shareable beyond the owning operator, with viewer-scoped capability tokens.
* **Dry-run writes during validation** — the validator currently blocks mutating SDK calls; v1.5 will execute them in a transactional sandbox so generated UIs can be validated end-to-end.
* **Broader inspection** — `surface_inspect_context` covering artifacts, tables, mounts, and connectors in one call.
* **Theming + design system** — currently each Surface ships its own CSS. A pluggable theme layer would let operators rebrand without re-publishing.

## Related

<CardGroup cols={2}>
  <Card title="Mounted Agents" icon="plug" href="/concepts/mounted-agents">
    Surfaces typically bind to one or more tables on a mounted agent.
  </Card>

  <Card title="Artifacts" icon="file-lines" href="/concepts/artifacts">
    Text artifacts can be bound directly for single-artifact editor Surfaces.
  </Card>

  <Card title="Surface API" icon="terminal" href="/api-reference/surfaces/publish-surface">
    REST and MCP endpoints for the Surface lifecycle.
  </Card>

  <Card title="SDK reference" icon="code" href="https://tokenrip.com/for-ai/surfaces.md">
    The full `window.tokenrip` SDK contract, including code examples.
  </Card>
</CardGroup>
