@drupal-canvas/headless
v0.1.1
Published
Framework-agnostic core of the Drupal Canvas Headless SDK: draft preview sessions, draft-aware content clients, and component metadata exposure for decoupled frontend apps.
Readme
@drupal-canvas/headless
Framework-agnostic core of the Drupal Canvas Headless SDK: draft preview sessions, draft-aware content clients, and component metadata exposure for decoupled frontend apps.
The Canvas Headless module lets the Drupal Canvas editor embed your frontend app, so editors preview their work — draft content included — rendered by the app itself, with the app's components registered in Canvas. Draft previews include the markers and geometry Canvas needs for selection and drag-and-drop, while published pages keep normal application markup.
This package is the framework-neutral app side of that integration. Most apps use a framework adapter instead of this package directly:
@drupal-canvas/headless-next(Next.js)@drupal-canvas/headless-astro(Astro)@drupal-canvas/headless-nuxt(Nuxt)@drupal-canvas/headless-tanstack-start(TanStack Start)
Installation
npm install @drupal-canvas/headlessType-checking with skipLibCheck: false can surface errors from a transitive
dependency's type declarations (jsona, via the JSON:API client); the
skipLibCheck: true default of framework tsconfigs avoids them.
Entry points
The subpaths keep browser bundles free of Node-only code and vice versa:
@drupal-canvas/headless— isomorphic: the protocol constants and theDraftDatasession contract.@drupal-canvas/headless/client— browser-only: the draft session state machine, the<canvas-draft-session>element, and preview geometry helpers.@drupal-canvas/headless/server— server-side, edge-safe: the draft server with its activation, renewal, and exit flows, the draft-aware content clients, and CSP helpers.@drupal-canvas/headless/components-endpoint— Node-only: the component metadata endpoint handler and the build-time component manifest.@drupal-canvas/headless/component-registry— Node-only: generates component implementation registry source.@drupal-canvas/headless/vite— Node-only: the shared component registry plugin for adapters built on Vite.@drupal-canvas/headless/preview.css— styles empty slot and region drop targets in draft previews.
Writing a framework adapter
Use an existing adapter if one exists for your framework. Writing a new one is mostly wiring, and the adapter packages listed above are worked examples of every step:
Implement
DraftServerAdapterfrom@drupal-canvas/headless/server: how your framework reads and sets cookies, flips its draft or preview flag, and redirects.Create the draft server and mount its flows as routes. The flows take a web
Requestand answer a webResponse:import { createDraftServer } from '@drupal-canvas/headless/server'; const server = createDraftServer({ adapter: myFrameworkAdapter }); // GET /api/draft -> server.enableDraftMode(request) // POST /api/draft/renew -> server.renewDraftSession(request) // POST /api/disable-draft -> server.disableDraftMode()Mount
createComponentMetadataHandler()from@drupal-canvas/headless/components-endpointas a route, with both itsGETandOPTIONShandlers.Provide the component implementation registry —
canvasComponentRegistry()from@drupal-canvas/headless/vitefor Vite-based frameworks, or generated source from@drupal-canvas/headless/component-registry— and expose aCanvasComponentTreerenderer that consumes it.In draft mode, the renderer must emit Canvas boundaries and use
@drupal-canvas/headless/preview.cssfor empty drop targets.Wire the client side: render the
<canvas-draft-session>element, or the React<DraftSession>from@drupal-canvas/headless-react, with the session state your server gathered.To refresh after Canvas auto-saves without reloading the document, pass
refreshDatato React'sDraftSession, or handleDRAFT_SESSION_REFRESH_EVENTwhen using<canvas-draft-session>.Expose data access:
server.getClient()andserver.fetchPage(), surfaced however your framework reaches per-request state.
