Setting Up Sanity Visual Editing / Presentation
Visual Editing is a mode of editing content directly on the site. Editor sees the site in iframe, clicks an element, the field opens in Sanity Studio. Sanity Presentation Tool is the official plugin. Works via Content Source Maps — Sanity adds metadata about source to each text fragment.
Installation
npm install @sanity/presentation # in Sanity Studio
npm install @sanity/visual-editing # in Next.js
Studio Setup
// sanity.config.ts
import { presentationTool } from '@sanity/presentation'
export default defineConfig({
plugins: [
structureTool(),
presentationTool({
previewUrl: {
previewMode: {
enable: '/api/draft-mode/enable',
disable: '/api/draft-mode/disable',
},
origin: process.env.SANITY_STUDIO_PREVIEW_URL || 'http://localhost:3000',
},
}),
],
})
Next.js Draft Mode and Visual Editing
// app/api/draft-mode/enable/route.ts
import { validatePreviewUrl } from '@sanity/preview-url-secret'
import { client } from '@/lib/sanity/client'
import { draftMode } from 'next/headers'
export async function GET(req: Request) {
const { isValid, redirectTo = '/' } = await validatePreviewUrl(
client.withConfig({ token: process.env.SANITY_API_TOKEN! }),
req.url
)
if (!isValid) {
return new Response('Invalid secret', { status: 401 })
}
draftMode().enable()
redirect(redirectTo)
}
// components/VisualEditingProvider.tsx
'use client'
import { enableVisualEditing } from '@sanity/visual-editing/next-pages-router'
import { useEffect } from 'react'
export function VisualEditingProvider() {
useEffect(() => {
return enableVisualEditing()
}, [])
return null
}
Content Source Maps
Content Source Maps enable Sanity to link text on page to specific field in Studio:
const client = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: 'production',
apiVersion: '2024-01-01',
useCdn: false,
stega: {
enabled: true, // enable Content Source Maps
studioUrl: process.env.NEXT_PUBLIC_SANITY_STUDIO_URL!,
},
})
Timeline
Setting up Visual Editing with Presentation Tool and Draft Mode — 1–2 days.







