👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

Draft mode

During runtime, switch between an optimized production mode and an authorized mode to fetch draft content and render edit overlays.

This example works with App Router in Next.js.

Endpoint to enable draft mode

// app/api/draft/route.ts

import { validatePreviewUrl } from '@sanity/preview-url-secret'
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

import { client } from '@/sanity/lib/client'
import { token } from '@/sanity/lib/token'

const clientWithToken = client.withConfig({ token })

export async function GET(request: Request) {
  const { isValid, redirectTo = '/' } = await validatePreviewUrl(
    clientWithToken,
    request.url,
  )

  if (!isValid) {
    return new Response('Invalid secret', { status: 401 })
  }

  draftMode().enable()

  redirect(redirectTo)
}

Endpoint to disable draft mode

// app/api/disable-draft/route.ts

import { draftMode } from 'next/headers'
import { NextRequest, NextResponse } from 'next/server'

export function GET(request: NextRequest) {
  draftMode().disable()
  const url = new URL(request.nextUrl)
  return NextResponse.redirect(new URL('/', url.origin))
}

Presentation tool integration

When these endpoints are set up, you may configure Presentation to automatically enable draft mode as needed:

// sanity.config.ts

import {defineConfig} from 'sanity'
import {presentationTool} from 'sanity/presentation'

export default defineConfig({
  // ...

  plugins: [
    presentationTool({
      locate,
      previewUrl: {
        origin:
          typeof location === 'undefined'
            ? 'http://localhost:3000'
            : location.origin,
draftMode: {
enable: '/api/draft',
disable: '/api/disable-draft',
},
}, }), ], })

Was this article helpful?