Preview Mode
Note: This feature is superseded by Draft Mode.
Examples
- WordPress Example (Demo)
- DatoCMS Example (Demo)
- TakeShape Example (Demo)
- Sanity Example (Demo)
- Prismic Example (Demo)
- Contentful Example (Demo)
- Strapi Example (Demo)
- Prepr Example (Demo)
- Agility CMS Example (Demo)
- Cosmic Example (Demo)
- ButterCMS Example (Demo)
- Storyblok Example (Demo)
- GraphCMS Example (Demo)
- Kontent Example (Demo)
- Umbraco Heartcore Example (Demo)
- Plasmic Example (Demo)
- Enterspeed Example (Demo)
- Makeswift Example (Demo)
In the Pages documentation and the Data Fetching documentation, we talked about how to pre-render a page at build time (Static Generation) using getStaticProps
and getStaticPaths
.
Static Generation is useful when your pages fetch data from a headless CMS. However, it’s not ideal when you’re writing a draft on your headless CMS and want to preview the draft immediately on your page. You’d want Next.js to render these pages at request time instead of build time and fetch the draft content instead of the published content. You’d want Next.js to bypass Static Generation only for this specific case.
Next.js has a feature called Preview Mode which solves this problem. Here are instructions on how to use it.
Step 1: Create and access a preview API route
Take a look at the API Routes documentation first if you’re not familiar with Next.js API Routes.
First, create a preview API route. It can have any name - e.g. pages/api/preview.js
(or .ts
if using TypeScript).
In this API route, you need to call setPreviewData
on the response object. The argument for setPreviewData
should be an object, and this can be used by getStaticProps
(more on this later). For now, we’ll use {}
.
res.setPreviewData
sets some cookies on the browser which turns on the preview mode. Any requests to Next.js containing these cookies will be considered as the preview mode, and the behavior for statically generated pages will change (more on this later).
You can test this manually by creating an API route like below and accessing it from your browser manually:
If you open your browser’s developer tools and visit /api/preview
, you’ll notice that the __prerender_bypass
and __next_preview_data
cookies will be set on this request.
Securely accessing it from your Headless CMS
In practice, you’d want to call this API route securely from your headless CMS. The specific steps will vary depending on which headless CMS you’re using, but here are some common steps you could take.
These steps assume that the headless CMS you’re using supports setting custom preview URLs. If it doesn’t, you can still use this method to secure your preview URLs, but you’ll need to construct and access the preview URL manually.
First, you should create a secret token string using a token generator of your choice. This secret will only be known by your Next.js app and your headless CMS. This secret prevents people who don’t have access to your CMS from accessing preview URLs.
Second, if your headless CMS supports setting custom preview URLs, specify the following as the preview URL. This assumes that your preview API route is located at pages/api/preview.js
.
<your-site>
should be your deployment domain.<token>
should be replaced with the secret token you generated.<path>
should be the path for the page that you want to preview. If you want to preview/posts/foo
, then you should use&slug=/posts/foo
.
Your headless CMS might allow you to include a variable in the preview URL so that <path>
can be set dynamically based on the CMS’s data like so: &slug=/posts/{entry.fields.slug}
Finally, in the preview API route:
- Check that the secret matches and that the
slug
parameter exists (if not, the request should fail). - Call
res.setPreviewData
. - Then redirect the browser to the path specified by
slug
. (The following example uses a 307 redirect).
If it succeeds, then the browser will be redirected to the path you want to preview with the preview mode cookies being set.
Step 2: Update getStaticProps
The next step is to update getStaticProps
to support the preview mode.
If you request a page which has getStaticProps
with the preview mode cookies set (via res.setPreviewData
), then getStaticProps
will be called at request time (instead of at build time).
Furthermore, it will be called with a context
object where:
context.preview
will betrue
.context.previewData
will be the same as the argument used forsetPreviewData
.
We used res.setPreviewData({})
in the preview API route, so context.previewData
will be {}
. You can use this to pass session information from the preview API route to getStaticProps
if necessary.
If you’re also using getStaticPaths
, then context.params
will also be available.
Fetch preview data
You can update getStaticProps
to fetch different data based on context.preview
and/or context.previewData
.
For example, your headless CMS might have a different API endpoint for draft posts. If so, you can use context.preview
to modify the API endpoint URL like below:
That’s it! If you access the preview API route (with secret
and slug
) from your headless CMS or manually, you should now be able to see the preview content. And if you update your draft without publishing, you should be able to preview the draft.
Set this as the preview URL on your headless CMS or access manually, and you should be able to see the preview.
More Details
Good to know: during rendering
next/router
exposes anisPreview
flag, see the router object docs for more info.
Specify the Preview Mode duration
setPreviewData
takes an optional second parameter which should be an options object. It accepts the following keys:
maxAge
: Specifies the number (in seconds) for the preview session to last for.path
: Specifies the path the cookie should be applied under. Defaults to/
enabling preview mode for all paths.
Clear the Preview Mode cookies
By default, no expiration date is set for Preview Mode cookies, so the preview session ends when the browser is closed.
To clear the Preview Mode cookies manually, create an API route that calls clearPreviewData()
:
Then, send a request to /api/clear-preview-mode-cookies
to invoke the API Route. If calling this route using next/link
, you must pass prefetch={false}
to prevent calling clearPreviewData
during link prefetching.
If a path was specified in the setPreviewData
call, you must pass the same path to clearPreviewData
:
previewData
size limits
You can pass an object to setPreviewData
and have it be available in getStaticProps
. However, because the data will be stored in a cookie, there’s a size limitation. Currently, preview data is limited to 2KB.
Works with getServerSideProps
The preview mode works on getServerSideProps
as well. It will also be available on the context
object containing preview
and previewData
.
Good to know: You shouldn't set the
Cache-Control
header when using Preview Mode because it cannot be bypassed. Instead, we recommend using ISR.
Works with API Routes
API Routes will have access to preview
and previewData
under the request object. For example:
Unique per next build
Both the bypass cookie value and the private key for encrypting the previewData
change when next build
is completed.
This ensures that the bypass cookie can’t be guessed.
Good to know: To test Preview Mode locally over HTTP your browser will need to allow third-party cookies and local storage access.