4.8 KiB
| title | aliases | tags | sources | created | updated | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Live Preview — Server-Side |
|
|
|
2026-05-15 | 2026-05-15 |
Overview
Server-side Live Preview is for frameworks that support React Server Components (e.g. Next.js App Router). It works differently from wiki/payloadcms/live-preview-client: instead of streaming form-state diffs, it triggers a full server roundtrip on every document save (draft save, autosave, or publish).
Flow: Admin Panel emits window.postMessage → front-end catches it → calls router.refresh() → Next.js re-fetches fresh data from the wiki/payloadcms/local-api.
Not applicable to: Next.js Pages Router, React Router, Vue 3, Nuxt.js, Svelte (use wiki/payloadcms/live-preview-client instead).
React / Next.js App Router
Install
npm install @payloadcms/live-preview-react
Usage pattern
Two files: a server page component + a thin 'use client' wrapper.
page.tsx (Server Component):
import { RefreshRouteOnSave } from './RefreshRouteOnSave'
import { getPayload } from 'payload'
import config from '../payload.config'
export default async function Page() {
const payload = await getPayload({ config })
const page = await payload.findByID({
collection: 'pages',
id: '123',
draft: true,
})
return (
<>
<RefreshRouteOnSave />
<h1>{page.title}</h1>
</>
)
}
RefreshRouteOnSave.tsx (Client Component):
'use client'
import { RefreshRouteOnSave as PayloadLivePreview } from '@payloadcms/live-preview-react'
import { useRouter } from 'next/navigation.js'
export const RefreshRouteOnSave = () => {
const router = useRouter()
return (
<PayloadLivePreview
refresh={() => router.refresh()}
serverURL={process.env.NEXT_PUBLIC_PAYLOAD_URL}
/>
)
}
The RefreshRouteOnSave component must be a Client Component because it subscribes to window.postMessage.
Building Your Own Refresh Component
Install the base package (framework-agnostic):
npm install @payloadcms/live-preview
| Export | Purpose |
|---|---|
ready({ serverURL }) |
Tells Admin Panel the front-end is ready to receive messages |
isDocumentEvent(event, serverURL) |
Checks if a MessageEvent is a document-level event from the Admin Panel |
Minimal implementation
import { isDocumentEvent, ready } from '@payloadcms/live-preview'
import { useCallback, useEffect, useRef } from 'react'
export const RefreshRouteOnSave = ({ refresh, serverURL }) => {
const hasSentReadyMessage = useRef(false)
const onMessage = useCallback((event) => {
if (isDocumentEvent(event, serverURL)) refresh()
}, [refresh, serverURL])
useEffect(() => {
window.addEventListener('message', onMessage)
if (!hasSentReadyMessage.current) {
hasSentReadyMessage.current = true
ready({ serverURL })
}
return () => window.removeEventListener('message', onMessage)
}, [serverURL, onMessage])
return null
}
Key Takeaways
- Server-side only for RSC frameworks — requires
router.refresh()(Next.js App Router pattern); not for SPA-style routing - Roundtrip on save — less real-time than client-side (
useLivePreview); updates appear only after a document save event - Enable Autosave — set
versions.drafts.autosave.interval: 375to make server-side feel responsive - Split Client/Server —
RefreshRouteOnSavemust be'use client'; the page component stays a Server Component - Base package —
@payloadcms/live-previewprovidesready+isDocumentEventfor custom non-React implementations - CSP gotcha — if your front-end sets
Content-Security-Policy, addframe-ancestors: "self" localhost:* https://your-site.comto allow the Admin Panel iframe
Troubleshooting
| Symptom | Fix |
|---|---|
| Updates lag compared to client-side | Enable Autosave with low interval (375ms) |
| Iframe refuses to connect | Add Admin Panel domain to CSP frame-ancestors directive |
Related
- wiki/payloadcms/live-preview — iframe config, breakpoints, mode selection
- wiki/payloadcms/live-preview-client —
useLivePreviewhook for SPAs - wiki/payloadcms/live-preview-frontend — server vs client decision guide
- wiki/payloadcms/local-api — what
router.refresh()hits under the hood - wiki/payloadcms/versions-autosave — enable for responsive server-side preview
Sources
raw/live-preview__server.md- https://payloadcms.com/docs/live-preview/server