This Friday: Hear from Sanity + Vercel experts on AI and better personalization in e-commerce

Static site deployment with preview workflow for Next.js and Sanity

3 repliesLast updated: Dec 2, 2025

Hi! I was curious what methods people use to deploy their sites with a static site generator (in my case, Next.js). I want the production site to be static, but have a non-static version to do previews. We host the production site on S3, but can likely host a preview site elsewhere, if needed.
Anyone have thoughts/examples of workflows (drafts, webhooks, etc.) that people use to control when things go to prod while also allowing for edited content to be previewed?

(also, not sure if this channel is the right place for this -- lmk and thanks!)
AI Update

Great question! This is a common setup for Sanity + Next.js sites, and there are several proven approaches to handle static production deployments with dynamic previews. Here's how people typically handle this workflow:

The Standard Setup

Production (Static on S3): Use Next.js Static Export (output: 'export') to generate a fully static site that you deploy to S3/CloudFront. This queries Sanity's published content.

Preview Site (Dynamic): Host a separate Next.js instance (on Vercel, Netlify, or any Node.js host) that runs in dynamic mode and uses Next.js Draft Mode to show unpublished drafts from Sanity.

Triggering Production Rebuilds

You have a few solid options for controlling when your static site gets rebuilt:

Option 1: Webhooks (Most Common)

Set up a Sanity webhook that triggers your build pipeline when content changes. Webhooks are GROQ-powered, so you can filter them to only fire on published documents (not drafts) using filters like !(_id in path("drafts.**")). This gives you precise control over when production updates happen.

Your webhook can call your CI/CD pipeline (GitHub Actions, AWS CodeBuild, etc.) to rebuild and deploy to S3. You can also customize the webhook payload using GROQ projections to include exactly the data your build process needs.

Option 2: Sanity Functions

Sanity Functions are serverless functions that run on Sanity's infrastructure and can react to document events. They're currently an experimental feature with APIs subject to change, but they offer a way to trigger your deployment pipeline without hosting your own webhook endpoint.

Functions can listen for document publish events and call your CI/CD API to kick off a rebuild. The main advantage is that everything stays within your Sanity project, but be aware this feature is still evolving.

Option 3: Manual Deploys

For smaller teams or less frequently updated content, you might just trigger builds manually through your CI/CD dashboard when ready to publish. Simple and reliable!

The Preview Workflow

For the preview site, set up an API route that enables Draft Mode:

// app/api/draft/route.ts
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const secret = searchParams.get('secret')
  const slug = searchParams.get('slug')
  
  // Validate secret token
  if (secret !== process.env.SANITY_PREVIEW_SECRET) {
    return new Response('Invalid token', { status: 401 })
  }
  
  draftMode().enable()
  redirect(slug || '/')
}

Then in your data fetching, use Sanity's perspective API to fetch drafts when in preview mode:

const client = createClient({
  // ...config
  perspective: draftMode().isEnabled ? 'previewDrafts' : 'published',
  useCdn: !draftMode().isEnabled
})

You can add a "Preview" button in Sanity Studio that links editors to your preview site with the draft mode URL, making it seamless for content creators to see their changes before publishing.

Alternative: ISR Instead of Full Static

If you're open to hosting your production site somewhere that supports server-side features (not pure S3), consider using Incremental Static Regeneration (ISR) instead. This lets you:

With ISR, you'd use revalidateTag() or revalidatePath() in an API route triggered by Sanity webhooks for instant updates when content changes. This eliminates the wait time for full rebuilds while keeping most of the benefits of static generation.

The Bottom Line

Your S3 static export approach is totally valid—especially if you want zero server costs and maximum simplicity. The most common pattern is:

This gives you full control over the production deployment timing while keeping the preview experience smooth for your content team!

Show original thread
3 replies

Was this answer helpful?

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Related contributions