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

# Design UI with an AI Agent in DesignJS

> Walk through a complete AI-assisted design session: start the canvas, connect your agent, and iterate on a hero section from prompt to polished UI.

DesignJS gives your AI agent direct read/write access to a live HTML/CSS canvas, so you can describe what you want in plain language and the agent builds it visually — no copy-paste between code and a browser preview required. This guide walks through a complete workflow: starting the canvas, connecting an agent, adding a hero section, and iterating until the design looks right.

## Prerequisites

* DesignJS repository cloned and dependencies installed (`pnpm install`)
* An MCP-compatible agent configured — Claude Code, Cursor, or VS Code with the MCP extension
* If you haven't run `designjs init` yet, see the [quickstart](/quickstart)

***

## The workflow

<Steps>
  <Step title="Start the canvas">
    Run the dev server from the repo root:

    ```bash theme={null}
    pnpm dev
    ```

    The canvas opens at `http://localhost:3000`. The WebSocket bridge starts automatically on `127.0.0.1:29170`. You'll see a connection indicator in the top-right corner of the editor shell — it turns green when at least one peer (your agent's MCP server) is connected.

    <Tip>
      Keep the browser window visible while working with an agent. You'll review changes in real time without needing to manually refresh.
    </Tip>
  </Step>

  <Step title="Verify the agent is connected">
    In your agent session, call `ping` before doing anything else. It's a zero-argument health check that confirms the MCP server has an active WebSocket route to the canvas:

    ```json theme={null}
    // Tool call
    {
      "tool": "ping",
      "params": {}
    }

    // Expected response
    {
      "pong": true,
      "at": 1713456789012
    }
    ```

    If `ping` times out or returns an error, the canvas WebSocket bridge isn't reachable. Check that `pnpm dev` is still running and the browser tab is open.
  </Step>

  <Step title="Capture the current canvas state">
    Before adding anything, have the agent take a screenshot to understand the current layout. This is the visual baseline the agent will build on:

    ```json theme={null}
    // Tool call
    {
      "tool": "get_screenshot",
      "params": {
        "scale": 2,
        "format": "png"
      }
    }

    // Response
    {
      "dataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
      "width": 1280,
      "height": 800
    }
    ```

    `scale: 2` returns a high-DPI screenshot at twice the CSS pixel dimensions — useful for seeing fine typographic detail. The agent embeds `dataUrl` as an image in its context and can reason about what's on the canvas before making any changes.

    <Info>
      You can also scope a screenshot to a single artboard by passing `artboardId`. Use `list_artboards` first to get the id.
    </Info>
  </Step>

  <Step title="Describe what you want">
    Tell the agent what to build. Be specific about layout, content, and tone — the more concrete the prompt, the fewer revision cycles you'll need:

    > "Add a full-width hero section with a dark navy background (`#0f172a`), a bold white headline that reads 'Ship design and code together', a one-line subheadline in slate-400, and a primary CTA button that says 'Get started free' in indigo."

    The agent translates this into an `add_components` call with raw HTML and Tailwind classes.
  </Step>

  <Step title="Agent adds the component">
    The agent calls `add_components` with the HTML it generates. The `target` parameter is optional — omit it to append to the canvas root, or pass a parent `componentId` to nest the new content inside an existing section:

    ```json theme={null}
    // Tool call
    {
      "tool": "add_components",
      "params": {
        "html": "<section class=\"w-full bg-[#0f172a] py-24 px-8 flex flex-col items-center text-center gap-6\"><h1 class=\"text-5xl font-bold tracking-tight text-white\">Ship design and code together</h1><p class=\"text-lg text-slate-400 max-w-xl\">DesignJS gives AI agents visual awareness of your HTML/CSS canvas. Describe, iterate, and export — no translation gap.</p><a href=\"#\" class=\"inline-flex items-center gap-2 rounded-lg bg-indigo-600 px-6 py-3 text-sm font-semibold text-white hover:bg-indigo-500 transition-colors\">Get started free</a></section>"
      }
    }

    // Response
    {
      "componentIds": ["comp-a1b2c3"]
    }
    ```

    Save the returned `componentId` — you'll use it in the next steps to scope refinements to this specific element.

    <Note>
      Tailwind v4 classes resolve natively in the canvas iframe (loaded via CDN), so arbitrary values like `bg-[#0f172a]` and responsive variants work without any configuration.
    </Note>
  </Step>

  <Step title="Agent verifies the result visually">
    After inserting the component, the agent captures another screenshot to confirm the visual output matches the intent:

    ```json theme={null}
    // Tool call
    {
      "tool": "get_screenshot",
      "params": {
        "scale": 2,
        "format": "png"
      }
    }
    ```

    If the layout, color, or typography looks off, the agent can read the current CSS for the component before making targeted adjustments:

    ```json theme={null}
    // Tool call — read CSS for the hero section specifically
    {
      "tool": "get_css",
      "params": {
        "componentId": "comp-a1b2c3"
      }
    }
    ```
  </Step>

  <Step title="Agent refines styles">
    When the agent identifies a specific property to tweak — such as adding more vertical spacing or softening the button border radius — it uses `update_styles` to target the component directly by id:

    ```json theme={null}
    // Tool call — increase vertical padding and round the button
    {
      "tool": "update_styles",
      "params": {
        "componentId": "comp-a1b2c3",
        "styles": {
          "padding-top": "7rem",
          "padding-bottom": "7rem"
        }
      }
    }

    // Response
    {
      "styles": {
        "padding-top": "7rem",
        "padding-bottom": "7rem"
      }
    }
    ```

    <Tip>
      For compound refinements — like adjusting multiple nested elements — it's often faster to have the agent call `get_html` on the component, revise the HTML string in context, and use `add_components` with `target` to replace the section rather than chaining many `update_styles` calls.
    </Tip>
  </Step>

  <Step title="Review in the browser">
    Switch to the browser tab with the canvas open. Everything the agent just added and refined is rendered live — you're looking at real HTML and CSS, not a preview approximation.

    If something still needs adjusting, you can either:

    * **Tell the agent** — describe the change in natural language and continue the loop
    * **Edit directly** — click the component in the canvas, use the style panel on the right, and the agent can re-read the state with `get_screenshot` or `get_html` on the next turn

    Your changes and the agent's changes converge on the same GrapesJS component model. Press `Cmd+S` (or `Ctrl+S`) to save the canvas to `.designjs.json`.
  </Step>
</Steps>

***

## Targeting components precisely

When the canvas has multiple sections, you want the agent to operate on the right element rather than the entire document.

**Use `get_selection` to target whatever is clicked:**

Select a component in the canvas editor (click it in the canvas or the layers panel), then ask the agent to call `get_selection`:

```json theme={null}
// Tool call
{
  "tool": "get_selection",
  "params": {}
}

// Response
{
  "componentIds": ["comp-a1b2c3"]
}
```

Pass that id directly to `update_styles`, `get_html`, `get_css`, or `get_jsx`. This is the fastest way to tell the agent "work on this exact thing."

**Use `get_tree` for structural context:**

If the agent needs to understand the component hierarchy before deciding where to insert content, `get_tree` returns the full recursive component tree:

```json theme={null}
// Tool call
{
  "tool": "get_tree",
  "params": {
    "depth": 3
  }
}
```

Limiting `depth` keeps the response concise for large documents.

***

## Working with artboards

If your canvas has multiple artboards (for example, a desktop and mobile layout), scope `get_screenshot` to a specific frame to avoid ambiguity:

```json theme={null}
{
  "tool": "get_screenshot",
  "params": {
    "artboardId": "artboard-desktop-01",
    "scale": 2,
    "format": "png"
  }
}
```

Use `list_artboards` to enumerate artboard ids and dimensions before scoping any tool call.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Export to React" icon="file-code" href="/guides/export-to-react">
    Convert your finished canvas design to a `.tsx` component using `get_jsx`.
  </Card>

  <Card title="Manage design tokens" icon="palette" href="/guides/css-variables">
    Use `get_variables` and `set_variables` to maintain a consistent color and spacing system across your canvas.
  </Card>
</CardGroup>
