📝 Marketing Site + CMS
The most common Vercel architecture: a headless CMS (Sanity, Contentful, Storyblok) connected to Next.js with ISR. Editors publish content, webhooks trigger targeted revalidation, and the site stays fast globally — with zero full rebuilds.
How It Works
Editor publishes in CMS
Content editor updates a blog post, landing page, or banner in Sanity/Contentful. Clicks 'Publish'.
CMS fires webhook
CMS sends a POST request to /api/revalidate with the content type and slug.
revalidateTag() runs
API route calls revalidateTag('blog-post-123') — only the affected page regenerates, not the entire site.
Next request gets fresh page
The next user hitting that URL gets the regenerated page, served from CDN. All other pages unaffected.
Key Vercel Features
⚡ ISR + Webhooks
On-demand revalidation via revalidateTag(). Only the changed page regenerates. A 10K-page site revalidates one page in seconds.
👁️ Draft Mode
Editors bypass ISR cache to preview unpublished content. Essential for editorial workflows — see changes before they go live.
🔗 Preview Deployments
Every PR gets a live preview URL. Design and content teams review real running pages, not Figma mockups.
🖼️ next/image
Auto WebP/AVIF conversion, responsive sizing, lazy loading. Hero images get priority prop for fast LCP.
✏️ next/font
Self-hosted fonts with zero layout shift. Google Fonts or custom fonts loaded with font-display: swap.
📊 Speed Insights
Real-user Core Web Vitals. Track actual visitor experience, not synthetic lab scores. Critical for SEO.
Webhook Revalidation — Code
// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const secret = request.headers.get('x-webhook-secret');
if (secret !== process.env.REVALIDATION_SECRET) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json();
const { type, slug } = body;
// Targeted revalidation — only affected pages
revalidateTag(`${type}-${slug}`); // e.g., 'blog-post-123'
revalidateTag(type); // e.g., 'blog' (listing page)
revalidateTag('homepage'); // homepage shows latest posts
return NextResponse.json({ revalidated: true, tags: [type, slug] });
}
// In your page component:
async function getBlogPost(slug: string) {
const post = await fetch(`https://cdn.sanity.io/...`, {
next: { tags: ['blog', `blog-${slug}`] }
});
return post.json();
}Popular CMS Options
| CMS | Best For | Vercel Integration |
|---|---|---|
| Sanity | Developer-friendly, real-time collaboration, GROQ query language | First-class Vercel integration. Visual Editing, webhook revalidation, Draft Mode. |
| Contentful | Enterprise content management, structured content, rich API | Webhook → revalidateTag(). Preview API for Draft Mode. GraphQL or REST. |
| Storyblok | Visual editor for non-technical users, block-based content | Visual Editor integration. Webhooks for revalidation. Bridge for live preview. |
| Payload | Self-hosted, full control, TypeScript-native, open-source | Can run on Vercel Postgres. API routes for content delivery. Full customization. |
| WordPress (headless) | Existing WordPress content, familiar editing experience | WPGraphQL → Next.js ISR. Webhook plugin for revalidation on publish. |