Skip to content

Headless Preview Configuration

See docs/superpowers/specs/2026-03-16-preview-mode-scheduled-publishing-design.md for the canonical design. Approach: Kjac.HeadlessPreview NuGet package + Next.js Draft Mode (new tab, not iframe).

Original Research (below) — kept for reference

Section titled “Original Research (below) — kept for reference”

Umbraco 17 does not have a native “Save and Preview” → external frontend URL feature. The built-in preview renders using Umbraco’s own templating engine, which is not applicable in a headless setup.

1. Content Delivery API — Draft Content Access

Section titled “1. Content Delivery API — Draft Content Access”

Umbraco’s Content Delivery API supports fetching unpublished/draft content via two request headers:

HeaderValuePurpose
PreviewtrueEnables draft content in API responses
Api-KeyConfigured API keyAuthorizes access to unpublished content

Configuration (appsettings.json):

{
"Umbraco": {
"CMS": {
"DeliveryApi": {
"Enabled": true,
"PublicAccess": true,
"ApiKey": "your-preview-api-key-here"
}
}
}
}

Next.js App Router has built-in Draft Mode support.

Implementation plan:

  1. Create API route apps/web/src/app/api/draft/route.ts:

    • Accepts secret, path, and siteKey query params
    • Validates secret against PREVIEW_SECRET env var
    • Calls draftMode().enable()
    • Redirects to the requested path
  2. Modify cms-client fetch calls to detect draft mode and add Preview: true + Api-Key headers

  3. Create API route apps/web/src/app/api/draft/disable/route.ts to exit draft mode

Two options to wire up the backoffice “Preview” button:

Community package (GitHub) that replaces the preview button behavior. Install via:

Terminal window
dotnet add package Kjac.HeadlessPreview

Note: Compatibility with Umbraco 17 needs verification. Works with Umbraco 15.

Section titled “Option B: Custom Preview Controller (Recommended)”

Create a custom controller in apps/cms/Savoy.Cms/Controllers/PreviewController.cs that:

  1. Receives the content ID from the backoffice
  2. Resolves the content’s URL path and siteKey
  3. Redirects to http://localhost:3000/api/draft?secret={SECRET}&path={PATH}&siteKey={SITE_KEY}

This is more maintainable than a third-party package dependency.

VariableWherePurpose
UMBRACO_DELIVERY_API_KEYCMS + Next.jsAPI key for preview requests
PREVIEW_SECRETCMS + Next.jsShared secret for draft mode activation