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

# Canvas Iframe Embed

> Embed a public canvas into your product with an iframe

## Overview

You can embed a public Agent Canvas into your own product using a standard HTML `<iframe>`, so your end users view canvas insights directly inside your app — no Upsolve account required, and **no DNS or CNAME setup**.

Optionally, you can white-label the share link so it shows **your own domain** instead of `ai-hub.upsolve.ai`.

## Prerequisites

1. An Agent Canvas with a **public link enabled** — open the Canvas share modal and toggle **Public link** on.
2. The public link's **access token** — shown in the share modal when the public link is on. It is the last path segment of the share URL.

## Embed the canvas (the only required step)

Build a page in your product and drop in an iframe pointing at the Upsolve canvas link:

```html theme={null}
<iframe
  src="https://ai-hub.upsolve.ai/shared/canvas/{accessToken}?hideHeader=1"
  width="100%"
  height="800"
  style="border: none;"
  allow="clipboard-write"
></iframe>
```

* Replace `{accessToken}` with the token from your share modal.
* `?hideHeader=1` hides the canvas name and "Read-only" badge for a chrome-free embed (see [URL Parameters](#url-parameters)).
* For on-premise deployments, replace `ai-hub.upsolve.ai` with your instance's hostname.

That's it. The `/shared/canvas/:token` route sends `Content-Security-Policy: frame-ancestors *`, so the page can be embedded from any origin. Your users see **your** app's page in the address bar; the canvas renders inside the frame. You do **not** need a custom domain or any DNS changes for this.

## (Optional) White-label the share link with your own domain

By default the share modal generates links against `ai-hub.upsolve.ai`. If you'd rather the copyable link show your own domain, set a **Custom Share Domain**:

1. Go to **Project Settings → Sharing**.
2. Enter your **Custom Share Domain** — the base that replaces the `ai-hub.upsolve.ai/shared/canvas` portion of the link, e.g. `insights.yourcompany.com/canvas`. A live preview shows the resulting link.
3. Save.

From this point on, every canvas's public link resolves to `https://<your-domain>/<accessToken>` — e.g. `https://insights.yourcompany.com/canvas/{accessToken}`.

<Info>
  The Custom Share Domain **only rewrites the link string** Upsolve generates — it does not change where the canvas is served. You decide what that URL does:

  * **Serve it from your own app (no DNS setup).** Route that path in your product (e.g. `/canvas/:token`) to a page you build that iframes the Upsolve canvas — the token is right there in the URL, so your page just renders `<iframe src="https://ai-hub.upsolve.ai/shared/canvas/{token}?hideHeader=1">`. This is the lightest option and needs no CNAME.
  * **Point the domain at Upsolve (CNAME / reverse proxy).** Forward the domain to your Upsolve instance so `https://<your-domain>/shared/canvas/{token}` reaches Upsolve's `/shared/canvas/:token` route directly. If you proxy, keep the `frame-ancestors *` response header so the page can still be framed.
</Info>

## URL Parameters

| Parameter    | Value | Effect                                                              |
| ------------ | ----- | ------------------------------------------------------------------- |
| `hideHeader` | `1`   | Hides the canvas name and "Read-only" badge for a chrome-free embed |

## How It Works

The `/shared/canvas/:token` route serves response headers that allow cross-origin framing (`Content-Security-Policy: frame-ancestors *`), configured for Vercel (cloud), nginx (cloud), and nginx (on-prem). All other Upsolve routes remain restricted to same-origin framing.

Embedding works because of that header alone — the outer page can live on any domain (yours). The Custom Share Domain is purely cosmetic for the link; it changes what the copyable URL says, not how the canvas is served.

## Security

* The canvas is **read-only** — end users cannot modify data or run queries.
* Access is gated by the access token in the URL; revoking the public link (toggling it off in the share modal) immediately invalidates the token.
* No authentication or Upsolve account is required for viewers.
