> ## 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.

# Architecture

> How the three services, packages, and data flow fit together.

## System Overview

Avocado Studio is a pnpm monorepo with four apps and eight packages:

```mermaid theme={null}
graph TD
    subgraph Clients["Inbound channels — pick any (or all)"]
        direction TB
        Editor["<b>Content Studio (:4100)</b><br/>Vite + React<br/>Chat panel · live preview iframe"]
        MCP["<b>MCP Server</b><br/>stdio + streamable HTTP<br/>Claude Desktop · Claude Code · any MCP host"]
        Jira["<b>Jira integration</b><br/>webhook + polling<br/>review · execute · preview · publish"]
    end

    subgraph Orchestrator["Orchestrator (:4200) — Fastify API"]
        O1["AI planning (LLM)"]
        O2["Operation validation"]
        O3["Session state + undo/redo"]
        O4["Publishing pipeline"]
    end

    subgraph Site["Site (:3000) — Next.js"]
        S1["Renders BlockInstance pages"]
        S2["Draft mode / Published mode"]
        S3["Block manifest API"]
    end

    Editor -->|"HTTP (REST + SSE)"| Orchestrator
    MCP -->|"HTTP (REST)"| Orchestrator
    Jira -->|"HTTP (REST)"| Orchestrator
    Editor <-->|"postMessage"| Site
    Orchestrator <-->|"HTTP"| Site
```

The orchestrator has **three parallel front doors**: the Content Studio web app for humans, the MCP server for AI assistants, and the Jira integration for ticket-driven workflows. All three go through the same operation pipeline — Zod validation, undo history, version log, demo-mode gating — so anything you can do in the web editor, you can do from Claude Desktop, Claude Code, or a Jira ticket (and vice versa). See [MCP Server](/integration/mcp-server) and [Jira Integration](/integration/jira) for setup.

## Data Flow: From Chat to Preview

When a user sends a message in the Content Studio, here's what happens:

```
1. Content Studio → Orchestrator  POST /chat/start (user message + page context)
                                   → returns streamId
2. Content Studio → Orchestrator  GET /chat/stream?streamId=… (SSE subscribe)
3. Orchestrator → LLM             Sends prompt with block schemas + page state
4. LLM → Orchestrator             Returns structured edit plan (JSON)
5. Orchestrator                   Validates operations against Zod schemas
6. Orchestrator → Content Studio  Streams plan + results via SSE
7. Orchestrator → Site            Bumps draft version
8. Site                           Re-fetches draft, re-renders blocks
9. Site → Content Studio          postMessage confirms preview updated
```

## Packages

The monorepo includes eight shared packages:

| Package                            | Purpose                                                                                                                                                            |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `@avocadostudio-ai/shared`         | Zod schemas for PageDoc, BlockInstance, Operation, EditPlan. Block registry. Shared types across all apps.                                                         |
| `@avocadostudio-ai/blocks`         | 20 built-in block renderers (Hero, CTA, FAQ, Gallery, etc.). Each block is a React component with a typed Zod schema.                                              |
| `@ai-site-editor/preview-adapter`  | PreviewBridge component that runs inside the site iframe. Handles postMessage communication with the Content Studio, block selection overlays, and CSS highlights. |
| `@ai-site-editor/site-sdk`         | SDK for integrating AI editing into any Next.js 15+ site. Provides route handlers, draft mode utilities, and content resolution for the Content Studio.            |
| `@ai-site-editor/editor-puck`      | Puck-based visual drag-and-drop editor, including the chat sidebar prototype. Generates the same ops as chat mode and publishes via the orchestrator.              |
| `create-ai-site-editor`            | CLI scaffolder that generates a Next.js site wired to the orchestrator (editor API routes, block manifest, draft mode, optional CMS template).                     |
| `@ai-site-editor/migration-sdk`    | Utilities for migrating existing content into the PageDoc / BlockInstance shape.                                                                                   |
| `@ai-site-editor/immersive-widget` | Embeddable widget used for immersive / full-bleed block experiences.                                                                                               |

## Communication Protocols

### Content Studio ↔ Orchestrator: HTTP + SSE

The Content Studio communicates with the orchestrator via REST API and Server-Sent Events:

* `POST /chat/start` — Start a streamed run, returns a `streamId`
* `GET /chat/stream?streamId=…` — Subscribe to the stream via SSE
* `POST /chat` — Non-streaming variant (immediate response)
* `GET /draft/pages` — Fetch current draft page state
* `POST /ops` — Apply hand-authored operations (bypassing the planner)
* `POST /history/undo`, `POST /history/redo` — Undo/redo operations
* `POST /publish` — Publish draft to production

### Content Studio ↔ Site: postMessage

The Content Studio embeds the site in an iframe. They communicate via the `site-editor/v1` postMessage protocol:

* **Content Studio → Site**: Request block highlight, navigate to page, refresh preview
* **Site → Content Studio**: Report selected block, confirm preview updated, send block manifest

### Orchestrator ↔ Site: HTTP

The site fetches draft content from the orchestrator when in draft mode:

* `GET /draft/pages` — All draft pages for the current session
* `GET /draft/slugs` — Available page slugs

## Session State

The orchestrator maintains **per-session state** for each editing session:

* **Draft pages** — Current page content with all pending edits
* **Operation history** — Full undo/redo stack
* **Edit plans** — Generated plans awaiting approval
* **Session config** — Selected AI provider, model tier, locale

Session state is scoped per session ID. Multiple users editing different sessions don't interfere with each other. State is persisted to a SQLite database (`.data/orchestrator.db`, via `better-sqlite3` + WAL) with synchronous transactional writes on every mutation, so crash recovery is automatic.

**SQLite is the working copy, not the source of truth.** Your CMS / JSON file / custom store is the origin; SQLite holds drafts, undo stacks, and chat history scoped per session. On the first chat for a fresh session, the orchestrator calls the configured [`CmsAdapter.getPages()`](/integration/cms-adapters) to seed SQLite. On publish, `onPublish(pages)` writes back. That separation is what lets the same chat UX work against any upstream store without per-integration handshakes.

<Note>
  The orchestrator runs as a single instance with a local SQLite file. Multi-replica horizontal scaling — which would require moving state to a network-accessible store (Postgres, Turso/libSQL, Redis, etc.) — is on the roadmap but not implemented today.
</Note>

## Publishing Pipeline

Publishing promotes draft content to production:

```mermaid theme={null}
flowchart LR
    Draft["Draft (orchestrator)"] --> PT["PublishTarget"] --> Prod["Production (your site)"]
```

The `PublishTarget` interface is pluggable. Three built-in targets ship in the box:

* **`site-contract`** — POSTs pages + assets to the remote site's `/api/editor/publish` endpoint. Selected when `siteOrigin` is supplied.
* **`git`** — Serializes draft pages to JSON, commits, and pushes to a Git branch. A Vercel deploy hook wired to that branch auto-builds.
* **`deploy-hook`** — Calls a raw `VERCEL_DEPLOY_HOOK_URL` and polls the Vercel API for deployment status.

Register your own via `registerPublishTarget()` to integrate with any workflow — S3, GitLab Pages, Netlify, a CMS API, a custom CI/CD pipeline. See [How it Works — Publishing](/how-it-works#publishing) for the full interface.
