Previewing drafts
A preview route enables draft mode and switches reads to the drafts perspective, so an editor sees unpublished work on the real site.
Preview is three moving parts, and the security of it lives in the first.
1. A secret, not a query parameter
The API issues a short-lived preview secret. The preview route validates it before enabling draft mode. Enabling preview on the strength of ?preview=1 would publish every draft on the site to anyone who guessed it.
2. Draft mode
export async function GET(request: Request) {
const secret = new URL(request.url).searchParams.get('secret')
if (!(await isValidPreviewSecret(secret))) return new Response('Invalid secret', { status: 401 })
;(await draftMode()).enable()
return Response.redirect(new URL('/', request.url))
}3. Reads that follow it
const { isEnabled } = await draftMode()
const { data } = await contentQuery({
query,
params,
perspective: isEnabled ? 'drafts' : 'published',
// Never cache a preview read.
revalidate: isEnabled ? 0 : 60,
})Remember what drafts means: the draft-over-published overlay, not "only drafts". A published document with no draft still appears — which is what makes a preview of a whole site coherent rather than mostly empty.
Turning it off
;(await draftMode()).disable()Give editors a visible way to do it. A preview session that persists silently is how someone ends up reporting a bug about content that is not live yet.
