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

# Hand it to your own coding agent

> The recommended way to bring an existing site into Avocado Studio: give the integration to the coding agent that already knows your codebase, working in your repo through your normal review flow.

This is the path we recommend, and the one every production integration has used.

You already run a coding agent — Claude Code, Codex, Cursor, or another. It has your codebase, your component library, your CMS client, your conventions and your git history. Our onboarding agent has none of that and has to discover it from scratch inside a repository it has never seen.

So do not switch tools. Install the skills below, point your agent at them, let it work on a branch, and review the diff the way you review any other diff.

<Note>
  **What this costs scales with pages × components**, not with the framework. Two
  small Contentful sites — a Next blog with 4 entries in 2 locales (8 pages, 3
  components marked) and an Astro bookshelf with 8 pages across 3 templates —
  took an agent about **25 and 13 minutes** of run time to integrate, plus a
  person's first pass through the editor. As a rough guide: minutes per
  distinct component to declare and mark up, plus the one-time wiring; a site
  with a few templates is an hour or less, and a design system with dozens of
  components and a CMS in several languages is days. The skills make the work
  correct and ordered; what makes it long is how many components there are.
</Note>

## Start here: install the skills

```bash theme={null}
npx @avocadostudio-ai/skills
```

Run that in your repo, then tell your agent: *"add Avocado Studio to this site."*

It writes five skills into `.claude/skills/` and `.agents/skills/` — `avocado`
routes, and `avocado-integrate` is the one for this job — plus an `AGENTS.md`
and a `CLAUDE.md` that point at them. Nothing else is touched: no routes, no
config, no dependencies. An `AGENTS.md` or `CLAUDE.md` you already have is never
overwritten; if yours does not mention Avocado, the command says so, and you add
the pointer line yourself. `--dry-run` prints what it would write.

<Note>
  **Why not a prompt on this page?** Because a web page cannot be versioned
  against what npm serves, and ours drifted — the quickstart said `0.11.9` while
  the registry served `0.13.1`, and the guides for existing sites taught a
  `registerBlock` call that does not compile. The skills ship inside the packages,
  so an install carries exactly its own version's instructions, and re-running the
  command after an upgrade replaces them. They are also tested: a suite in the
  package reads every skill and fails on an API call that would not compile.
</Note>

The skills are the instructions, and they are all of them. `avocado` routes;
`avocado-integrate` runs this job; `avocado-blocks` declares components and
marks up renderers; `avocado-cms` covers content that lives in Sanity, Storyblok
or another headless CMS; `avocado-demo` builds a throwaway. Between them they
carry what this page used to hold as a 400-line prompt — moved to where it can
be kept true, and tested.

## Before you start

* **Node 22+** and your usual package manager.
* **One of the supported frameworks:**

  * **Next.js 15 or 16, App Router.** If you are on 16, the agent must use `proxy.ts` rather than `middleware.ts` (at the project root, or in `src/` if the app uses one) and give `config` as a static object literal — Next 16 reads it by static analysis and cannot read one returned from a factory.
  * **Astro 5 or later**, through `@avocadostudio-ai/astro` — see [the Astro integration](/integration/astro-integration). No adapter is needed to edit against `astro dev`; one is needed to preview a deployed site. `avocado-integrate` has an Astro branch that follows that page. If the copy lives inline in `.astro` or JSX markup rather than in a CMS or data files, [file-backed sites](/integration/file-backed-sites) is the recipe for moving it out.

  An older version of either (Next 14, Astro 3) is an upgrade first, and a separate change.
* **Your own dev server** — `next dev`, `astro dev` — for registration and the coverage check. In [library mode](/quickstart) (Next.js only) the orchestrator is not a service you start: it is mounted inside your own app at `http://localhost:3000/api/avocado`, so it is up exactly when your dev server is. Everything before registration never talks to it at all. If your project has no orchestrator mounted yet, [the quickstart's route](/quickstart#5-mount-the-orchestrator-inside-your-app) is the whole of it. `http://localhost:4200` is the *standalone* server's address, and it is what `avocado-register` defaults to — pass `--orchestrator` unless that is really what you are running.
* **The editor UI**, also for the last step only, and it *is* a process you start: `npx @avocadostudio-ai/cli start`. See [Open it](#open-it). Nothing in the integration itself needs it, which is why it is easy to reach the end without it.
* **One `siteId`, spelled the same in three places:** `createSitePage` (on Astro, the integration's `siteId`), the orchestrator — the `createOrchestrator` mount, or the standalone server's registry — and `avocado-register --id`. They disagree and the page asks for a draft session the orchestrator never seeded — which looks like the editor showing published content for no reason.
* **An Anthropic, OpenAI or Google API key** on the orchestrator. Avocado runs on your keys; it never resells tokens.
* **A branch.** The agent will touch your route files. Give it somewhere to be wrong.

## If your agent cannot load skills

Some agents have no skill support, and some read files only when told to. The
skills are plain Markdown on disk after the command above, so point at them
directly. Paste this:

```markdown theme={null}
Add Avocado Studio to this project.

Read `.agents/skills/avocado/SKILL.md` first and follow where it routes —
`avocado-integrate` for this job, plus `avocado-blocks` when you get to
declaring components and `avocado-cms` if this site's content comes from a CMS.
Those files are the specification; follow them rather than anything you
remember about this library.

Work on a branch. Survey and report back before you change anything, and wait
if the survey surprises you.

If there is a preview route, its first line must be
`requireEditorContext(await searchParams)` from
`@avocadostudio-ai/site-sdk/draft`, before it reads anything unpublished.

Finish on numbers, not on "it builds": `editableCoverage` per page, measured
against the dev server's editor render with each block's `props` passed in, and
`panelCoverage` overall, targeting 100% and zero findings. If you cannot reach
that, list every remaining gap with the block type and the field path. Then run
`npx avocado qa` from the site's directory with the dev server up, and do not
call the integration done until it exits 0.

Then report: files changed, the block table with the props you deliberately
left undeclared, the coverage figures, the `avocado qa` summary, and anything
you had to guess about my codebase.
```

That is the whole prompt, because the instructions are in the repo rather than
in the message. They came from the package, so they match the version you
installed — which a pasted prompt cannot.

The skills also link out to the reference pages as they need them. If you would
rather read the whole job yourself before starting it, the route is
[concepts](/concepts), then [the integration contract](/sites/manual), then
[the Next.js reference](/integration/nextjs-integration) or
[the Astro one](/integration/astro-integration),
[custom blocks](/integration/custom-blocks), [coverage](/integration/coverage)
and [the QA gate](/integration/qa) — with [field table](/integration/field-table),
[CMS adapters](/integration/cms-adapters) and
[multilingual](/integration/multilingual) if your content is in a CMS.

## Reading the docs from a local checkout

If your agent is behind a proxy or you would rather it read from disk, point it at the `docs-site/` directory of your Avocado checkout instead of the URLs:

```
Required reading, in order:
  docs-site/concepts.mdx
  docs-site/sites/manual.mdx
  docs-site/integration/nextjs-integration.mdx   (or astro-integration.mdx)
  docs-site/integration/custom-blocks.mdx
  docs-site/integration/coverage.mdx
  docs-site/integration/qa.mdx
```

## Give the agent Avocado's own tools

The [MCP server](/integration/mcp-server) exposes 49 tools over Model Context Protocol — stdio or Streamable HTTP — and works with any MCP host, including Claude Code, Codex, Cursor and Claude Desktop. Connecting it during the integration gives your agent two things the docs cannot:

* **Real pages and real blocks.** It can read the site's actual content and manifest from the orchestrator instead of guessing from the code.
* **`avocado-check-editing-surface`.** The panel-coverage QA check as a tool, so the agent can grade its own work between passes rather than at the end.

## When the agent gets stuck

| Symptom | Likely cause | Fix |
| - | - | - |
| Imports `zod` or `@avocadostudio-ai/shared` directly and hits type errors | Reached past the package boundary | Every specifier must be `@avocadostudio-ai/site-sdk/*`, or `@avocadostudio-ai/astro/*` on Astro — types included: `import type { PageDoc } from "@avocadostudio-ai/site-sdk"`. Re-read the import rules in the `avocado` skill |
| `npx avocado-scope` fails with a 404 from the registry | The command lives in `@avocadostudio-ai/migration-sdk`; there is no package by that name | `npx -p @avocadostudio-ai/migration-sdk avocado-scope <url>`, plus `--allow-localhost` for a local dev server |
| Coverage reports gaps for fields that are empty on the page | `extractMarkedBlocks` output was passed to `editableCoverage` without each block's `props` | Pass the page's blocks: `extractMarkedBlocks(html, { blocks: page.blocks })`, with the page from `GET /api/editor/pages` — see [coverage](/integration/coverage#editablecoverage) |
| Coverage sits well below 100% and the gaps are all inside lists | Missing `editableScopeProps` on list rows | Point it at the scope section of [custom blocks](/integration/custom-blocks) |
| Markers are present but the overlay edits the wrong prop | A scope is missing, so bare paths resolve against the enclosing block | Same fix — the failure is silent and wrong, not silent and absent |
| Adds a wrapper for a scope and the layout breaks | The wrapper became the flex or grid item | `editableScopeProps(path, { display: "contents" })` |
| Registers custom blocks but the manifest returns built-ins | Registration ran too late, or import order clobbered it | Pass `registerBlocks` and `blockTypes` to `createEditorApiHandler` |
| Builds a `/preview` route | Confused embedded mode with the optional preview route group | Embedded mode, draft-mode cookies only, no `/preview` route |
| `config` export ignored on Next 16 | Returned from a factory | Static object literal in `proxy.ts` |
| The preview route answers a stranger with unpublished content | The route reads CMS drafts before it checks for the editor | Make `requireEditorContext(await searchParams)` from `@avocadostudio-ai/site-sdk/draft` the route's first line. It answers 404 to anything that is not an authorized editor render. Check it the way a stranger would: request the preview URL from a production build with no cookie and no secret |
| The editor frame is blank, "refused to display … in a frame" | The site's own `X-Frame-Options` or `frame-ancestors` refuses the editor's origin | `withAvocado` writes framing headers for `?__editor=1` requests from `EDITOR_CORS_ORIGINS` / `NEXT_PUBLIC_EDITOR_ORIGIN`. A site that sets its own headers has to admit the editor origins itself — see [Next.js integration](/integration/nextjs-integration#framing). `npx avocado qa` checks this in its preflight |
| Doesn't know what a `BlockInstance` is | Skipped the concepts page | Make it read `concepts.mdx` before anything else |

## After the agent finishes

If the agent ran `avocado-register`, the site is already registered and appears in the editor's dashboard on the next open or refresh. Otherwise run it yourself:

```bash theme={null}
cd /path/to/your/project
npx avocado-register --name "My Site" --orchestrator http://localhost:3000/api/avocado
```

The script will:

1. Work out the framework (Astro, Next.js or other), the package manager and the dev port from the project.
2. Take the draft secret from `--secret`, else from `DRAFT_MODE_SECRET` in `.env` or `.env.local`, else generate one.
3. POST the site config and the secret to `<ORCHESTRATOR_URL>/sites/register`, which answers whether the secret matches the orchestrator's `DRAFT_MODE_SECRET`.
4. **On a mismatch, stop and write nothing.** The editor sends its secret to your site with every preview; a site holding a different one shows published content in the frame. The message says where the right value lives — for a standalone orchestrator run from an Avocado checkout, `DRAFT_MODE_SECRET` in that checkout's `.env`, which the editor reads as `VITE_SITE_DRAFT_SECRET` — and to re-run with `--secret <value>`.
5. Otherwise write the file your framework reads, adding only missing keys: `.env.local` with `DRAFT_MODE_SECRET`, `ORCHESTRATOR_URL` and the `NEXT_PUBLIC_*` names on Next; `.env` with `DRAFT_MODE_SECRET`, `ORCHESTRATOR_URL` and `AVOCADO_SITE_ID` on Astro and anything else. `--secret` replaces a different value already there.
6. Print next steps in your package manager's spelling — `npm run dev`, `pnpm dev`, `yarn dev`.

Against an orchestrator with an access password, pass `--token` (it defaults to `ORCHESTRATOR_ACCESS_TOKEN`). The command also warns when the env file it wrote is not git-ignored, because the next `git add -A` would commit the secret.

An unreachable orchestrator is not a failure: the env file is still written, the command exits 0, and it says the secret could not be checked. `ORCHESTRATOR_URL` is written only once something answered there, or you named it — an address nothing replied at is a guess, and writing it would pin it for every later run.

<Note>
  **Registration is optional in library mode.** A library-mode mount already knows the one site it is mounted in and reports it from `GET /sites` whether or not anyone registered it. What registration adds is the name, preview URL and purpose in the orchestrator's registry — worth having, not a gate. Skipping it does not stop the site loading in the editor.
</Note>

## Open it

Two processes, in two terminals. The integration you just reviewed is only half
of what has to be running: it makes your app *editable*, and the editor UI is a
separate program that talks to it.

<Tabs>
  <Tab title="Your site">
    ```bash theme={null}
    npm run dev
    ```

    Your Next.js app on `http://localhost:3000`, with the orchestrator mounted inside it at `/api/avocado`.
  </Tab>

  <Tab title="The editor UI">
    ```bash theme={null}
    npx @avocadostudio-ai/cli start \
      --orchestrator http://localhost:3000/api/avocado \
      --preview      http://localhost:3000
    ```

    The prebuilt editor on `http://localhost:4100`.
  </Tab>
</Tabs>

This is the one thing in library mode you do start yourself. The orchestrator is
not a process — it is mounted inside your app — so it is easy to finish the
integration, open `http://localhost:4100` and find nothing listening, having
started everything the integration mentioned.

**Pass `--orchestrator`.** The CLI defaults to `http://localhost:4200`, the
standalone server, which is not what this project runs. `--preview` is the
origin the editor loads in its iframe — your site.

Then open `http://localhost:4100`, pick the site, and send one edit from the
chat panel to confirm the round trip.

## Troubleshooting

| Symptom | Likely cause | Fix |
| - | - | - |
| `avocado-register` says it could not reach the orchestrator | The URL is wrong, or your dev server is down | The default it tries is `http://localhost:4200`, the standalone server. In library mode there is no separate process to start: run your site's `dev` script and pass `--orchestrator http://localhost:3000/api/avocado`. Your env file was still written; re-run to finish the registry entry and check the secret. |
| Registered, but the site is not in the editor | The editor fetches `GET /sites` on mount and merges with localStorage | Hard-refresh the editor |
| `avocado-register` stops: the orchestrator has a `DRAFT_MODE_SECRET` and this site's does not match | The secret was generated, or the one in your env file is another project's | Re-run with `--secret <value>`, taking the value from `DRAFT_MODE_SECRET` in the orchestrator's `.env` (the editor's `VITE_SITE_DRAFT_SECRET`). Nothing was written, so there is nothing to undo |
| Warning: orchestrator has no `DRAFT_MODE_SECRET` | It started without one | Set `DRAFT_MODE_SECRET` in the orchestrator's env and restart |
| `http://localhost:4100` refuses the connection | The editor UI is a separate process and nothing started it | `npx @avocadostudio-ai/cli start --orchestrator http://localhost:3000/api/avocado --preview http://localhost:3000` — see [Open it](#open-it) |
| Site loads in the editor but nothing is clickable | Click-to-select is a toggle and defaults off | Turn on **Select an element** in the chat composer |

If your agent cannot finish, the fallback is not to start over by hand — it is to narrow the scope. Get the install and the editor API route landed and verified, then do the renderer markup block by block, checking coverage after each one.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.