The contract
Every adapter implements the same two-method interface from@ai-site-editor/orchestrator-core:
getPages()is called lazily on the first chat for a fresh session. Its result seeds SQLite so chat turns like “edit the homepage hero” resolve against your real content instead of a 404.onPublish()is called when a client POSTs to/publishon the library-mode handler with{ session, siteId }. The orchestrator reads the current draft from SQLite and hands the resultingPageDoc[]to the adapter. If you omitonPublish,/publishbecomes a200no-op (withwritten: falsein the response) and SQLite still holds the draft.
Bundled adapters
Two adapter implementations ship in@ai-site-editor/orchestrator-core/cms:
jsonFileAdapter
Reads PageDoc[] from a JSON file on disk. Smallest possible adapter — useful when your content is already checked into git, or for prototypes before you pick a real CMS.
PageDoc[] or an object with a pages key. Each entry is parsed through the lenient PageDoc schema, so partial or extra fields are tolerated.
editorApiAdapter
Fetches PageDoc[] from a site’s /api/editor/pages endpoint. Use this when your site already exposes a page-listing API, or when the orchestrator runs out-of-process from the site.
PageDoc schema are dropped from the seed and a warning is logged with the candidate index, slug, and first Zod issue path — pass logger: yourLogger if you want those routed to your own log sink.
Wiring it up
Library-mode integration (orchestrator mounted as a Next.js catch-all route inside your site) is the recommended pattern. One file, fully drop-in:getPages(), seeds SQLite, and the planner can immediately reason about your pages.
Publishing back
Onceadapter.onPublish is defined, your editor (or any client) can publish a session’s draft to the upstream store with one POST:
PageDoc[] to adapter.onPublish(pages). If the adapter has no onPublish, the route still returns 200 but with written: false — useful for sites that publish via CI / git commit rather than a runtime writeback.
Session scoping. When
adapter is set, sessions auto-scope to siteId (default "library") so they bypass the legacy demo-content seed path. If you see a chat returning demo blocks instead of your content, pass an explicit siteId to force the scope.Writing a custom adapter
If your content lives somewherejsonFileAdapter and editorApiAdapter don’t reach, write your own. The contract is small enough to inline:
createOrchestrator({ adapter: myCmsAdapter({ spaceId: "..." }) }). Failures inside getPages() are logged but non-fatal — the session simply starts empty.
If you build a non-trivial adapter (Storyblok, Hygraph, Payload, Directus, etc.) we’d love to merge it into examples/.
Custom block schemas
If your site renders custom block shapes (e.g. aHero with carouselImages instead of canonical imageUrl), register your schemas with the global block registry alongside the adapter:
lib/my-blocks.ts, call registerBlock("Hero", { schema, meta }) for each type you want to override. See Custom blocks for the full schema shape.
Example apps
Five working examples live underexamples/ in the repo. Each one boots in under two minutes:
| Example | Content store | Pattern | Port |
|---|---|---|---|
sample-site | Local JSON file | Zero-config starter — uses jsonFileAdapter | 3002 |
contentful-site | Contentful | Headless SaaS CMS | 3003 |
contentful-marketing-site | Contentful | Marketing-site flavor | 3006 |
sanity-site | Sanity | Headless + embedded Studio | 3004 |
strapi-site | Strapi v5 | Self-hosted open-source CMS | 3005 |
/api/avocado/[[...path]]/route.ts that mounts createOrchestrator({ adapter: ... }) (recommended), plus the legacy split-mode /api/editor/* route for sites that want the orchestrator deployed separately.
Contentful
Free Community plan is enough. The setup script creates the full content model (20 block types +page + siteConfig).
examples/contentful-site/README.md.
Sanity
The example ships with an embedded Sanity Studio at/studio alongside the Avocado editor.
http://localhost:3004 as a CORS origin in Sanity project settings (with credentials allowed).
Full walkthrough: examples/sanity-site/README.md.
Strapi
Self-hosted, open-source. The setup script generates Strapi v5 schema files from the Avocado block registry.page and site-config.
Full walkthrough: examples/strapi-site/README.md.
See also
- Next.js integration — full route-handler reference
- Block system — how
PageDocandBlockInstanceare shaped - Custom blocks — registering your own React components
- Publishing — how
onPublishties into the publish flow