Note
This is an experimental project.
An experimental ASP.NET Core / Blazor starter for frontends built for Canvas Headless.
The Canvas Headless module lets the Drupal Canvas editor embed this app, so editors preview their work, rendered by the app itself, with the app's components registered in Canvas.
cp .env.example .env # point CANVAS_SITE_URL at your Drupal site
dotnet runThe app serves on http://localhost:5210: any Drupal path (e.g. /page/1)
resolves through the Canvas content API and renders server-side. Register the
URL as a headless frontend in the Canvas editor's Headless frontends screen
and the editor embeds the app for drag-and-drop editing, syncing the component
library from Components/canvas/.
Requires the .NET 10 SDK. Node.js is only needed when changing styles:
npm install && npm run build:css regenerates wwwroot/css/app.css (Tailwind
CSS 4; the generated file is committed).
- Catch-all Drupal page rendering (
Program.cs): every request resolves through Drupal, with redirects, document head, and 404s handled. - The component library (
Components/canvas/): the same selected components as the JavaScript templates, one directory per component with its framework-neutralcomponent.ymlmetadata and a Blazor.razorimplementation. Naming note: where a component carries a prop named exactly like itself (heading,image,text,video), the class is*Componentand registered explicitly inProgram.cs, because a C# property cannot share its class's name. - Draft preview end to end: activation, PKCE-bound renewal, exit, CHIPS
cookies for the cross-site editor iframe, editor geometry markers, and the
DraftBannersession chrome. - The component metadata endpoint Canvas syncs the library from, protected by proof-by-redemption.
- Component preview thumbnails: the editor renders each library entry
through an isolated one-component document (
/api/canvas/component-preview, draft-session-only). The app names the stylesheets that document loads viaCanvasHeadlessOptions.ComponentPreviewStylesheets, so thumbnails match how components look on pages.
packages/ holds the C# port of the
@drupal-canvas/headless server core
and its ASP.NET Core binding — the integration layer the app builds on. They
live in this repository and are referenced as projects:
DrupalCanvas.Headless— the framework-agnostic protocol core: draft session flows (RFC 7523 assertion redemption at Drupal's token endpoint), draft-aware content fetching, rendered-page contracts, render helpers and the editor comment-marker format, CSP merging, andcomponent.ymldiscovery.DrupalCanvas.Headless.AspNetCore— endpoints (MapDrupalCanvasHeadless()), DI (AddDrupalCanvasHeadless(),AddDrupalCanvasComponents()), frame-ancestors middleware,.envconfiguration, the BlazorCanvasComponentTreerenderer, and the npm package's browser client served as static assets (pinned at@drupal-canvas/headless@0.5.0; seescripts/sync-client-assets.sh).
packages/tests/DrupalCanvas.Headless.Tests ports the
Canvas Headless JavaScript SDK's flows.test.ts
scenario-for-scenario; the AspNetCore suite covers the renderer's marker output
and the endpoints end-to-end, including the CHIPS Partitioned cookie
attributes. Keep the ported suite in step with the JS one — it is the
contract stopping the two protocol implementations from drifting.
dotnet test packages/DrupalCanvas.Headless.slnxBuilt at Acquia.