# Publication — point de branchement `interactive-page` ## Canal existant (ne pas dupliquer) | Élément | Emplacement | |---|---| | API | `app/api/notes/publish/route.ts` — `action: publish \| unpublish`, `mode?: simple \| ai \| interactive-page` | | UI | `components/note-editor/note-editor-toolbar.tsx` (menu Globe) + `InteractivePagePublishDialog` | | Page publique | `app/(public)/p/[slug]/page.tsx` → `/p/{publicSlug}` | | Fetch | `getPublishedNote(slug)` dans `app/actions/notes-publishing.ts` | | Templates | `lib/publish/types.ts` — `PUBLISH_TEMPLATES` = `magazine \| brief \| essay \| interactive-page` | ### Champs `Note` (Prisma) - `isPublic`, `publicSlug`, `publishedAt` - `publishedContent` — snapshot opaque (`String?`) : HTML aujourd’hui, **JSON PageSpecV1** pour `interactive-page` - `publishedTemplate` — discriminant de rendu - `publishedSourceHash` — détection stale (pas de régénération silencieuse) ## Branchement `interactive-page` 1. Étendre `PUBLISH_TEMPLATES` avec `'interactive-page'`. 2. Publish : générer/valider via `lib/interactive-page/` → stocker `JSON.stringify(PageSpecV1)` dans `publishedContent`, `publishedTemplate = 'interactive-page'`. 3. Rendu public : dans `PublishedNotePage`, si `publishedTemplate === 'interactive-page'` → parser → `` (SSR + hydrate démos). 4. Unpublish / stale : **même** cycle de vie que magazine/brief/essay (`publishedSourceHash` → badge « à régénérer »). ## Hors scope - `NotebookSite` `/c/[slug]`, `NoteShare` (collab privée), server actions legacy `publishNote` incomplets.