Skip to content

Content Flow & Live Preview

Sources: omni-cms-composable-cms/schemaTypes/lib/presentation/resolve.ts, omni-web-content-frontend/src/app/api/draft-mode/

Diagram Diagram

Configured in sanity.config.ts:

presentationTool({
resolve: resolve,
previewUrl: {
initial: previewOriginNl,
previewMode: {
enable: "/api/draft-mode/enable",
disable: "/api/draft-mode/disable",
},
},
allowOrigins: [previewOriginNl, previewOriginCom].filter(Boolean),
}),
VariableDomainCountries
SANITY_STUDIO_PREVIEW_ORIGIN_NL.nlNetherlands
SANITY_STUDIO_PREVIEW_ORIGIN_COM.comBelgium, France, Germany

The resolve.ts function maps Sanity documents to frontend URLs:

CountryExample URL
NLhttps://preview.hema.nl/kerst-inspiratie
BE (Dutch)https://preview.hema.com/nl-be/kerst-inspiratie
FRhttps://preview.hema.com/fr-fr/noel-inspiration
DEhttps://preview.hema.com/de-de/weihnachts-inspiration

nl-nl is the default locale (no prefix in the URL path).

GET /api/draft-mode/enable?sanity-preview-secret=<secret>&sanity-preview-perspective=<perspective>
  1. Validates the preview secret via @sanity/preview-url-secret
  2. Enables Next.js draftMode()
  3. Optionally sets perspective cookie (for Sanity Releases)
  4. Redirects to the target page
GET /api/draft-mode/disable

Clears the draft mode cookie and redirects back.

Draft mode supports Sanity Releases — scheduling content bundles. When a perspective cookie is set, the MFE fetches content from that specific release perspective.

async function isPreviewPerspectiveValid(perspective: string) {
const releases = await clientWithToken.fetch("releases::all()[state == 'active']{name}");
return perspectiveIds.every(id => id === 'drafts' || releaseIds.includes(id));
}

When draft mode is active, the client embeds invisible metadata in rendered strings. The Presentation Tool uses this to enable click-to-edit — clicking text in the preview opens the corresponding field in Studio.

All Sanity requests are tagged for observability:

requestTagPrefix: "omni-web-content"
// Draft requests get: "omni-web-content.draft"
  1. Add API routes: src/app/api/draft-mode/enable/route.ts and disable/route.ts
  2. Configure Sanity client with defineLive
  3. Use sanityFetch in your data layer (handles draft/published automatically)
  4. Register your MFE’s preview URL in the CMS sanity.config.ts:
    • Add origin to allowOrigins
    • Add URL resolution rules in resolve.ts
  5. Set env vars: SANITY_API_READ_TOKEN, NEXT_PUBLIC_SANITY_STUDIO_URL