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 toPageDoc, 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 isnext: >=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 blocks —
registerBlock, 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 fromdata- 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:
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
CmsAdaptercontract plusjsonFileAdapterandeditorApiAdapter. Working examples for JSON files, Contentful, Sanity and Strapi. - Publishing —
@avocadostudio-ai/site-sdk/publishdiffs 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, mountcreateOrchestrator({ 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 fileeditorApiAdapter— content fetched from your site’s own/api/editor/pagesendpoint
@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:
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 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 contract —
GET /api/editor/blocksreturns 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 byGET /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/publishaccepts 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:pnpm add @avocadostudio-ai/site-sdk(plus@avocadostudio-ai/orchestrator-corefor library mode)- Wrap
next.config.tswithwithAvocado - Create
app/api/editor/[...path]/route.tswithcreateEditorApiHandler - Replace
app/[[...slug]]/page.tsxwithcreateSitePage - Declare your own components as blocks, and mark up their renderers
- Run
npx avocado-register --name "My Site" --orchestrator http://localhost:3000/api/avocadofrom the project directory (the flag matters — the default is the standalone server on:4200) - Run the five verification
curlchecks, then coverage until it reports what you expect
Other frameworks
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.
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.
Related
- 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