Skip to main content
This page is the map of the published surface — what an Avocado integration consists of, which package subpath covers each part, and where the detailed guide for each one lives. Deciding who writes the integration, and how? That is bring your site in. This page assumes the decision is made and you want the reference. New to the project? Read core concepts first.

What you are integrating

Avocado is the operations layer for a site you already built. Your team edits through an AI chat editor and an optional visual editor; the edits arrive at your site as typed content operations — never as a code change. That vocabulary has no verb for “change a file”, so the boundary is not a policy you configure. It is the shape of the only thing that can cross. Integrating means declaring where that boundary sits: Five things have to be true when you are done: your components are declared, your content maps to PageDoc, the editor API answers, your renderers are marked up so a click on the page resolves to a field, and publishing writes back where you want it.
Next.js on the App Router is the supported path — 15 and 16 both. Every SDK helper that ships with adapters in the box is Next.js, as is every example app but one (examples/sample-site, examples/contentful-site, examples/contentful-marketing-site, examples/sanity-site, examples/strapi-site). If your site is Next.js, follow the Next.js integration walkthrough.Astro has its own package. @avocadostudio-ai/astro mounts all five routes, injects the preview bridge and handles Astro’s prerendering problem for you — your .astro components keep rendering, and nothing on the /core path below applies. examples/astro-site is the one non-Next.js example, and two gates drive it on every push.Other frameworks (Remix, SvelteKit, Nuxt, Hono, Cloudflare Workers) can be integrated with the SDK’s framework-agnostic /core primitives, but you will be a first mover — see other frameworks.

Which Next.js version

The SDK’s peer range is next: >=15.0.0, so both install, and the integration is the same on both except for one file: One caveat worth stating plainly: the example apps are on 15, so that is the version continuously exercised. The Next 16 path is shipped and documented rather than continuously tested, and it is the path a site created in the last few months will be on. If your site already has a middleware.ts or proxy.ts, note that Next allows exactly one per project. Compose yours with the SDK’s by hand — the helper assumes the file is new.

The supported path

Next.js integration

The canonical walkthrough. Two SDK helpers — createEditorApiHandler mounts the catch-all editor route, createSitePage is a drop-in app/[[...slug]]/page.tsx — plus npx avocado-register, five verification curl checks, and troubleshooting.

How it works in two helpers

You wire both to your existing content fetchers (getPage, getSlugs, getSiteConfig), then register the site with npx avocado-register. That is the skeleton. The rest of this page is the surface around it.

The integration surface

Everything below is published from @avocadostudio-ai/site-sdk at a subpath of its own. You will not need all of it; this is the map of what exists so you know what you are choosing between.

Your components are the blocks

On an existing site, the blocks are your own components, registered with a schema that says which of their props are content. That registration is the boundary: a prop you declare is editable, a prop you do not declare is not, and no amount of asking will change that.
  • Custom blocksregisterBlock, custom renderers, and how your components reach the manifest.
  • Field table — one declaration per block that derives the Zod schema, the property panel, the CMS projection and the merge back. Ships as @avocadostudio-ai/site-sdk/lens, with lens packs for Storyblok (/lens/storyblok) and Sanity (/lens/sanity) that encode each CMS’s own field conventions.
  • Built-in blocks — the 20 built-in types (Hero, CTA, FAQAccordion, Testimonials, Gallery, Stats, Carousel, Table and the rest). A starting catalogue for sites built from scratch, not the main event on a site that already exists.
  • Block system — how manifests, field metadata and validation fit together.

Marking up your renderers

The editor resolves a click on a rendered page back to a block and a field. That mapping comes from data- attributes your renderer emits, and @avocadostudio-ai/site-sdk/markers writes them for you: Only getPreviewWrapperProps is required. The other two mark individual fields, which is what inline text editing, the hover pills and the image buttons are found by — an optional pass over your own components, worth doing once the integration runs: Make the page directly editable. Two rules save a lot of debugging. The path in a marker must match the editablePath the field table declares — decoupled sources drift silently, and the symptom is an overlay that selects nothing. And a rich-text field rendered as React children must not be mutated in place by the live-draft overlay; the markers handle that distinction for you.

Keeping the preview clean

isEditorRender() from @avocadostudio-ai/site-sdk/draft answers “is this render inside the editor?” from a layout, where searchParams is not available. Gate your consent banner, analytics and tag manager on it:
Without it, one measured integration sent a page_view into the site’s own analytics for every block an editor clicked through, and put a cookie banner on top of the page being edited.

Proving it worked

Coverage checks

editableCoverage and panelCoverage, from @avocadostudio-ai/site-sdk/coverage, grade the integration: which declared fields the rendered page actually marks, and whether the property panel is usable for each block. The number is what tells you the integration is finished, rather than a spot check on the one page you happened to open.

Content, publishing and multilingual

  • CMS adapters — the CmsAdapter contract plus jsonFileAdapter and editorApiAdapter. Working examples for JSON files, Contentful, Sanity and Strapi.
  • Publishing@avocadostudio-ai/site-sdk/publish diffs the payload field by field against a restart-surviving baseline, so a target that writes diffs writes nothing for pages nobody touched.
  • Multilingual — one editable page per (document × language) for a CMS that localises per field, and the two traps that silently corrupt a dataset when the projection is wrong.

The rest of the published surface

Library mode: the orchestrator inside your site

If you would rather run the orchestrator inside your Next.js app than as a standalone service, mount createOrchestrator({ adapter }) from @avocadostudio-ai/site-sdk/server as a catch-all route and point it at a CmsAdapter that knows how to read your content. Two bundled adapters cover most cases:
  • jsonFileAdapter — content checked into git as a JSON file
  • editorApiAdapter — content fetched from your site’s own /api/editor/pages endpoint
Library mode needs one extra package: @avocadostudio-ai/orchestrator-core is an optional peer dependency of the SDK, so pnpm add @avocadostudio-ai/site-sdk alone does not pull it in — which keeps it out of installs that only render blocks and talk to a standalone orchestrator. Add it explicitly:
It publishes exactly two entry points, and everything you need is behind them: Anything deeper — a path into state/, http/, ops/ — is internal and will not resolve. If you find yourself needing one, that is a gap in the contract: get in touch rather than routing around it. It carries native dependencies (better-sqlite3, sharp). A bundler must be told to leave all of them alone — otherwise the native binary is bundled and crashes when it loads, and Turbopack fails the build over an optional peer you deliberately never installed. Wrapping your config applies both halves:
serverExternalPackages on its own is not enough here: transpilePackages, which library mode also needs, overrides it for a transitive dependency. See server externals.
Library mode is credentialed by default in production. createOrchestrator() gates every route. With no auth hook and neither ACCESS_PASSWORD_HASH nor ORCHESTRATOR_ACCESS_TOKEN set, it refuses every request under NODE_ENV=production — an unauthenticated publish endpoint on your own domain is not a default anyone should reach by forgetting something. To run it open on purpose, say so: auth: () => true.
Linking the packages instead of installing them? Install the two vendor SDKs yourself.
openai and @anthropic-ai/sdk are ordinary dependencies of @avocadostudio-ai/orchestrator-core, so a normal registry install already brings them and you can skip this. It matters when you point at a local checkout with file: or link:: your package manager symlinks the package without installing its dependency tree into your project, and Next externalises bare node_modules packages on the server — so the emitted require("openai") runs from your .next/ and looks in your node_modules, never the link target’s.Both are loaded at module scope, so a missing one is not a degraded feature. The route file fails to load and every endpoint answers 500, including ones that never touch a model:
This applies even if you only plan with one vendor — the handler is one module graph and it loads both. googleapis and @google/genai are different: they are genuinely optional peers, loaded through await import(...), and a mount runs fine without either. You do need @google/genai if you plan with Gemini or generate images with it.
Library mode is the lightest integration when your content is already PageDoc-shaped, and it sidesteps the standalone-orchestrator deployment entirely. See CMS adapters for the full pattern.

Integration model (high level)

Whichever framework you are on, the contract is the same:
  • Source of truth — an adopter-owned component registry in code: your own components, exposed through the SDK’s manifest.
  • Transport contractGET /api/editor/blocks returns the block manifest as JSON, generated by the SDK from your registry.
  • Preview bootstrap — Draft Mode cookies, set by GET /api/editor/draft?secret=…&redirect=… and cleared by GET /api/editor/draft/disable?redirect=….
  • Page render — in editor mode your page handler reads draft content from the orchestrator instead of your CMS, and mounts the editor overlay.
  • Publish — optionally, POST /api/editor/publish accepts the edited content back so you can write it to your CMS, file system or database.

Required endpoints

createEditorApiHandler mounts all five at once under a single catch-all route on Next.js — see the walkthrough for the one-file setup. On other frameworks you mount them yourself with the /core primitives.

Required environment variables

A mismatch between the editor’s VITE_SITE_DRAFT_SECRET and the site’s DRAFT_MODE_SECRET is the single most common failure — avocado-register surfaces it as a warning. It degrades to “the preview shows published content” rather than an error, which is why it goes unnoticed.

Adoption checklist

For a Next.js App Router project:
  1. pnpm add @avocadostudio-ai/site-sdk (plus @avocadostudio-ai/orchestrator-core for library mode)
  2. Wrap next.config.ts with withAvocado
  3. Create app/api/editor/[...path]/route.ts with createEditorApiHandler
  4. Replace app/[[...slug]]/page.tsx with createSitePage
  5. Declare your own components as blocks, and mark up their renderers
  6. Run npx avocado-register --name "My Site" --orchestrator http://localhost:3000/api/avocado from the project directory (the flag matters — the default is the standalone server on :4200)
  7. Run the five verification curl checks, then coverage until it reports what you expect
Steps 1–4 are an afternoon. Step 5 is the integration. For non-Next.js frameworks the conceptual steps are identical, but you implement the route handlers and the page-render branching by hand — see non-Next.js integration.

Other frameworks

First-mover territory — unless you are on Astro. Two frameworks have adapters in the box: Next.js, in @avocadostudio-ai/site-sdk/draft and /routes, and Astro, in @avocadostudio-ai/astro. Everywhere else the SDK’s /core primitives are framework-agnostic by design and the patterns work, but you are writing the adapter, and there is no support commitment on that path today.
On Astro, stop here and read the Astro integration. It is an install and one config block; none of the three options below apply. If your site is on neither, you have three honest options:

Wrap in a Next.js shell

Stand up a thin Next.js project that proxies to your existing backend, and use the standard Next.js integration. Fully supported, and where most people who try the non-Next.js path end up.

DIY with /core primitives

Implement the editor API contract by hand with createDraftEnableHandlerCore, createBlocksHandler, resolveDraftContextCore and friends. Worked examples for Hono and SvelteKit.

Hand it to your coding agent

Give the integration to Claude Code, Codex or Cursor. The guidance assumes Next.js; an agent that knows your framework can usually adapt it, and results vary.
The Next.js adapter is small — packages/site-sdk/src/draft-routes.ts is about 30 lines over the framework-agnostic core — so a working adapter for another framework is a bounded piece of work rather than a rewrite. If you want your framework supported first class, or you have built an adapter you would like folded in, get in touch.
  • Coverage checks — prove the integration is complete
  • Visual editor — opt-in drag-and-drop direct manipulation on the same blocks, same publishing pipeline, same orchestrator
  • Environment reference — every variable, grouped by what it configures
  • Native tools — the tool contract for connecting a PIM, a DAM, Unsplash or AI image generation to the planner
  • MCP server — 49 tools over Model Context Protocol, for any MCP host