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

# Canvas and frames

> The two units you work with every day. Everything else is built on these.

<img src="https://mintcdn.com/canvas-docs/XEIFdbLI8Xl-rNYx/images/canvas-frames-diagram.svg?fit=max&auto=format&n=XEIFdbLI8Xl-rNYx&q=85&s=fe2447997f716f8f3a01353a4f295578" alt="A VibeFlow canvas with five frames at different aspect ratios and an attached design system" style={{ width: "100%", borderRadius: "12px", marginBottom: "2rem" }} width="960" height="460" data-path="images/canvas-frames-diagram.svg" />

## Canvas

A **canvas** is a document you own at `/canvas/:id`. It holds your frames, your chat history, and a few pinned settings:

| What's on a canvas | What it does                                                             |
| ------------------ | ------------------------------------------------------------------------ |
| **Frames**         | The artboards visible in the viewport. Any number, any size.             |
| **Chat history**   | Every brief, every reply, every tool call. Multiple chats per canvas.    |
| **Design system**  | Optional, pinned to the canvas. Locks brand for every future generation. |
| **Style preset**   | Optional aesthetic (e.g. *Editorial*, *Glassmorphism*) layered on top.   |
| **Assets**         | Images you've uploaded or generated, addressable by the agent.           |

A canvas belongs to an organization and is **owner-scoped**. Other people in your org cannot edit it today (multiplayer is coming soon). They can clone a copy if you publish it to the community gallery.

### Creating a canvas

<CardGroup cols={3}>
  <Card title="From the home composer" icon="house">
    `/home` → toggle to **Canvas** → brief → **Generate**. You land on `/canvas/:id` with the agent already streaming.
  </Card>

  <Card title="From the canvas list" icon="grid-2">
    `/canvas` → **New canvas**. Blank canvas, then talk to the agent in chat.
  </Card>

  <Card title="From a community template" icon="copy">
    `/community` → pick a canvas template → **Use template**. You get an owned copy.
  </Card>
</CardGroup>

You can also create a canvas from your editor via the [MCP](/mcp/tools), then drive it from chat.

***

## Frame

A **frame** is a fixed-size artboard rendered as inline HTML inside an iframe on the canvas. That's the whole shape.

| Property    | Detail                                                                                                                                          |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Size        | Set per-frame. Common sizes: 1440 × 900 desktop, 1920 × 1080 slide, 1080 × 1080 social, 390 × 844 mobile, 1200 × 628 ad. Any custom size works. |
| Position    | `x`, `y` on the canvas. Drag with the mouse.                                                                                                    |
| Stack order | A `z` index per frame. Frames can overlap.                                                                                                      |
| Content     | Inline-styled HTML. No `<script>`, no form controls. Validated before render.                                                                   |
| Storage     | Inline on the frame, or spilled to a Convex blob when the HTML gets large.                                                                      |
| Editable    | Double-click to edit in place. Text, layout, deletes write back automatically.                                                                  |

Each frame is **independent**. Editing one never touches the others. Frames don't share state at runtime, but they do share your design system. A single agent change can update one or many frames in a single turn.

### Creating a frame

You almost never make frames by hand. The agent makes them in response to chat. The common patterns:

* *"Add a third slide with a chart of monthly revenue."* → one new frame, sized like the others.
* *"Build me a landing page, a 1080 social cut, and a mobile mock for the same launch."* → three frames, three sizes, same brand.
* *"Duplicate this frame and try a dark variant."* → `duplicate_frame` → tweak.

You can also drop a blank frame manually with the **F** keyboard shortcut, but those are local-only until the agent fills them.

***

## How the canvas renders

Each frame is **real HTML in an iframe** on the canvas. Not a screenshot, not a terminal sketch. What you see is what exports.

<div
  style={{
width: "100%",
maxWidth: "520px",
margin: "0 auto 1.5rem",
fontFamily:
  'ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif',
}}
>
  <div
    style={{
  padding: "8px 10px",
  borderRadius: "8px 8px 0 0",
  background: "#FAFAFC",
  border: "1px solid #E2E2E8",
  borderBottom: "none",
  fontSize: "10px",
  color: "#8A8AA0",
  letterSpacing: "0.04em",
}}
  >
    Canvas viewport · pan & zoom
  </div>

  <div
    style={{
  padding: "14px",
  background:
    "radial-gradient(circle at 1px 1px, #E2E2E8 1px, transparent 0) 0 0 / 16px 16px #F7F7FB",
  border: "1px solid #E2E2E8",
  borderTop: "none",
}}
  >
    <div
      style={{
    width: "100%",
    maxWidth: "360px",
    margin: "0 auto",
    borderRadius: "10px",
    background: "#FFFFFF",
    border: "1px solid #E2E2E8",
    boxShadow: "0 10px 28px rgba(15,20,19,0.1)",
    overflow: "hidden",
  }}
    >
      <div
        style={{
      padding: "6px 10px",
      borderBottom: "1px solid #E2E2E8",
      fontSize: "10px",
      color: "#8A8AA0",
      background: "#FAFAFC",
    }}
      >
        Frame · 1080 × 1080
      </div>

      <div
        style={{
      padding: "16px",
      background: "#FFFFFF",
    }}
      >
        <div
          style={{
        fontSize: "18px",
        fontWeight: 700,
        color: "#0F1413",
        marginBottom: "8px",
        lineHeight: 1.2,
      }}
        >
          Launch week
        </div>

        <div
          style={{
        fontSize: "12px",
        color: "#6B6B7B",
        lineHeight: 1.45,
        marginBottom: "12px",
      }}
        >
          On-brand HTML the agent wrote. Inline styles only.
        </div>

        <div
          style={{
        display: "inline-block",
        padding: "8px 14px",
        borderRadius: "8px",
        background: "#5B5BD6",
        color: "#FFFFFF",
        fontSize: "12px",
        fontWeight: 600,
      }}
        >
          Get started
        </div>
      </div>
    </div>
  </div>

  <div
    style={{
  marginTop: "8px",
  fontSize: "11px",
  color: "#6B6B7B",
  lineHeight: 1.5,
  textAlign: "center",
}}
  >
    Pixi positions the frame shell · the iframe renders your HTML · exports read the same DOM
  </div>
</div>

Two things follow from this:

1. **What you see is what exports.** PNG/PDF/PPTX walk the iframe DOM. There is no separate render target.
2. **Frames are sandboxed from each other.** They share the design system at *generation time* (via the agent prompt), not at *render time* (via shared DOM).

***

## What's persisted, what's local

| Lives in Convex                            | Lives only in your tab                               |
| ------------------------------------------ | ---------------------------------------------------- |
| Canvas record (name, design system, style) | Pan / zoom position                                  |
| Every frame (HTML, position, size, z)      | Selection state                                      |
| Every chat message and tool call           | Element pointers in the comment composer             |
| Generated images (R2-backed)               | Manually-dropped blank frames (`F` key) until filled |

If you close the tab mid-generation, the canvas survives. If you reload during an agent turn, the frames already created are still there. The agent's in-flight turn restarts cleanly from where it was.

***

## What a canvas is not

* **Not a design tool.** No vector tools, no pen, no boolean ops. Frames are HTML. You shape them by talking to the agent or editing the inline HTML.
* **Not a docs tool.** No long-form pages. Frames are bounded artboards. For long pages, generate a landing-page frame at 1440 × 4000+ and scroll inside it.
* **Not a runtime.** Generated React apps live in the [promote-to-app](/exports/promote-to-app) flow, not on the canvas. The canvas renders static HTML.

## Next

<CardGroup cols={2}>
  <Card title="The chat" icon="message" href="/concepts/the-chat">
    The agent loop. How it plans frames, what tools it calls.
  </Card>

  <Card title="Inline edit" icon="hand-pointer" href="/concepts/inline-edit">
    The AI Pointer. Click any element, drop a note, the agent edits exactly that.
  </Card>
</CardGroup>
