Skip to content
Writing Room

Preview on your site

View as Markdown

Preview opens the document on your site in draft mode, unpublished changes included. It’s off until you give it your site’s origin:

writingRoom({
  preview: {
    origin: 'https://example.com',
    pathname: (slug) => `/blog/${slug}`, // default: /posts/<slug>
  },
})
Option Default What it does
preview.origin — Your site’s origin. Setting preview turns on the room’s Preview button.
preview.enablePath /api/draft-mode/enable The route that checks the preview secret and turns on draft mode.
preview.pathname /posts/<slug> for post, /<type>/<slug> for other types (slug, type) => path: where a document is read on your site.

With more than one type, use the second argument:

pathname: (slug, type) => (type === 'caseStudy' ? `/case-studies/${slug}` : `/blog/${slug}`)

The room creates a one-hour preview secret and opens <origin><enablePath>?sanity-preview-secret=…&sanity-preview-pathname=…. Your site needs a route there that validates the secret and redirects:

  • Next.js (App Router): use next-sanity.

    // app/api/draft-mode/enable/route.ts
    import {defineEnableDraftMode} from 'next-sanity/draft-mode'
    import {client} from '@/sanity/client'
    
    export const {GET} = defineEnableDraftMode({
      client: client.withConfig({token: process.env.SANITY_API_READ_TOKEN}),
    })
  • Anything else (Astro, Nuxt, SvelteKit, Remix…): call validatePreviewUrl(client, request.url) from @sanity/preview-url-secret, turn on your framework’s draft or preview mode, and redirect to the redirectTo it returns.

Either way the site needs a Viewer token to check the secret, and its origin must be a CORS origin of your Sanity project.