You are integrating my Next.js project at [PROJECT_PATH] with Avocado Studio,
an open-source AI content operations platform. The full docs are at https://docs.avocadostudio.dev (or run locally — see below).
## Goal
Add the @ai-site-editor/site-sdk to my project so the Avocado Content Studio
can edit my content via Draft Mode, then register the site with the orchestrator
so it appears in the editor's dashboard. Same end state as if I had used the
built-in Onboarding agent.
## Required reading (in order)
1. https://docs.avocadostudio.dev/concepts — page model, blocks, operations, draft mode
2. https://docs.avocadostudio.dev/integration/nextjs-integration — the canonical contract
3. https://docs.avocadostudio.dev/integration/custom-blocks — only if my project has custom React components I want editable
4. https://docs.avocadostudio.dev/integration/non-nextjs — only if I'm not on Next.js
Read these pages BEFORE writing any code. Do not skim. The contract is exact.
## What to do
1. Inspect my project structure. Confirm it's Next.js 15 App Router. If it isn't, stop and ask me how to proceed.
2. Add `@ai-site-editor/site-sdk` to package.json and install it.
3. Mount the editor API as a single catch-all route at `app/api/editor/[...path]/route.ts`:
```ts
import { createEditorApiHandler } from "@ai-site-editor/site-sdk/routes"
import { getMyPages, publishMyPages } from "@/lib/my-cms"
export const { GET, POST, OPTIONS } = createEditorApiHandler({
getPages: () => getMyPages(),
onPublish: async (pages, config) => { await publishMyPages(pages, config); return { ok: true } },
publishSecret: process.env.PUBLISH_TOKEN,
})
```
This single helper mounts ALL of: `/api/editor/blocks`, `/api/editor/pages`, `/api/editor/draft`, `/api/editor/draft/disable`, `/api/editor/publish`. It validates `?secret=` against `DRAFT_MODE_SECRET`, rejects non-internal redirects, sets the draft cookie, and handles CORS preflight. Do NOT write these routes by hand.
4. Replace `app/[[...slug]]/page.tsx` with the SDK's `createSitePage` factory:
```tsx
import { createSitePage } from "@ai-site-editor/site-sdk/page"
import { getPage, getSlugs, getSiteConfig } from "@/lib/my-cms"
const { Page, generateStaticParams } = createSitePage({
siteId: "my-site",
getPage,
getSlugs,
getSiteConfig,
})
export default Page
export { generateStaticParams }
```
This handles draft mode detection, the editor overlay, navigation chrome, 404 fallbacks, and switching between published vs draft reads. Do NOT write loader branching logic by hand.
5. If my project has custom React components for hero / cta / faq / etc that aren't in the built-in block library, register them with the SDK following the custom-blocks doc and pass `getManifest` to `createEditorApiHandler`.
6. Run my dev server and verify:
- `GET /api/editor/blocks` returns a non-empty `blocks` array
- `GET /api/editor/draft?secret=<my-secret>&redirect=/` sets the draft cookie and redirects
- The site still renders normally without Draft Mode
7. **Register the site with the orchestrator** — run from inside my project directory:
```bash
npx avocado-register --name "My Site"
```
This bin script (shipped with `@ai-site-editor/site-sdk`) generates a
`DRAFT_MODE_SECRET` if `.env.local` doesn't already have one, writes the
required env vars, and POSTs the site config to `POST /sites/register` on
the orchestrator. After it succeeds, the site auto-appears in the editor's
dashboard the next time the editor is opened (or refreshed).
Make sure the orchestrator is running at http://localhost:4200 (or wherever
`$ORCHESTRATOR_URL` points) before you run this step.
## What NOT to do
- Do not invent endpoint paths or schemas. The contract is exact — the editor calls `/api/editor/draft` (not `/api/draft`), `/api/editor/blocks`, `/api/editor/pages`, `/api/editor/draft/disable`, `/api/editor/publish`. All five live under `/api/editor/*`.
- Do not write the draft routes by hand. Use `createEditorApiHandler` from `@ai-site-editor/site-sdk/routes` — it does secret validation and the internal-redirect check for you. These are security-critical and easy to get wrong.
- Do not modify my existing route handlers' published-data path. Draft Mode is additive.
- Do not commit `DRAFT_MODE_SECRET` to git. It goes in `.env.local` only.
- Do not refactor my existing components unless they need to be wrapped to expose props for AI editing.
- Do not register the site by hand-editing `.env.local` and asking me to add the site through the editor UI — use the `npx avocado-register` script in step 7.
## Verification checklist (run this at the end)
- [ ] `pnpm typecheck` (or my project's equivalent) passes
- [ ] My existing pages still render at their existing routes without Draft Mode
- [ ] `curl http://localhost:3000/api/editor/blocks` returns valid JSON with `blocks: [...]`
- [ ] `curl -i 'http://localhost:3000/api/editor/draft?secret=<secret>&redirect=/'` returns a 307 with the draft cookie set
- [ ] `curl -i 'http://localhost:3000/api/editor/draft?secret=wrong&redirect=/'` returns 401 or 403
- [ ] `curl -i 'http://localhost:3000/api/editor/draft?secret=<secret>&redirect=https://evil.com'` is rejected (must NOT 307 to evil.com)
- [ ] No `DRAFT_MODE_SECRET` value appears in any committed file
- [ ] `npx avocado-register --name "..."` returned a `registered` status with no warnings (warnings about secret mismatch are surfaced — flag them if present)
- [ ] `curl http://localhost:4200/sites?session=dev` includes my new site in the response
## Reporting
When you're done, tell me:
1. Which files you created or modified, with one-sentence reasons
2. The verification checklist results (one line each)
3. The exact `npx avocado-register` invocation you used and its output
4. Any warnings the orchestrator returned (especially about secret mismatch)