Implementing Live Preview in your app
While using Live Preview, the Admin panel emits a new window.postMessage
event every time a change is made to the document. Your front-end application can listen for these events and re-render accordingly.
Wiring your front-end into Live Preview is easy. If your front-end application is built with React, Next.js, Vue or Nuxt.js, use the useLivePreview
hook that Payload provides. In the future, all other major frameworks like Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See building your own hook for more information.
By default, all hooks accept the following args:
Path | Description |
---|---|
serverURL * | The URL of your Payload server. |
initialData | The initial data of the document. The live data will be merged in as changes are made. |
depth | The depth of the relationships to fetch. Defaults to 0 . |
apiRoute | The path of your API route as defined in routes.api . Defaults to /api . |
* An asterisk denotes that a property is required.
And return the following values:
Path | Description |
---|---|
data | The live data of the document, merged with the initial data. |
isLoading | A boolean that indicates whether or not the document is loading. |
React
If your front-end application is built with React or Next.js, you can use the useLivePreview
hook that Payload provides.
First, install the @payloadcms/live-preview-react
package:
Then, use the useLivePreview
hook in your React component:
Vue
If your front-end application is built with Vue 3 or Nuxt 3, you can use the useLivePreview
composable that Payload provides.
First, install the @payloadcms/live-preview-vue
package:
Then, use the useLivePreview
hook in your Vue component:
Building your own hook
No matter what front-end framework you are using, you can build your own hook using the same underlying tooling that Payload provides.
First, install the base @payloadcms/live-preview
package:
This package provides the following functions:
Path | Description |
---|---|
subscribe | Subscribes to the Admin panel's window.postMessage events and calls the provided callback function. |
unsubscribe | Unsubscribes from the Admin panel's window.postMessage events. |
ready | Sends a window.postMessage event to the Admin panel to indicate that the front-end is ready to receive messages. |
The subscribe
function takes the following args:
Path | Description |
---|---|
callback * | A callback function that is called with data every time a change is made to the document. |
serverURL * | The URL of your Payload server. |
initialData | The initial data of the document. The live data will be merged in as changes are made. |
depth | The depth of the relationships to fetch. Defaults to 0 . |
With these functions, you can build your own hook using your front-end framework of choice:
Here is an example of what the same useLivePreview
React hook from above looks like under the hood:
Example
For a working demonstration of this, check out the official Live Preview Example. There you will find examples of various front-end frameworks and how to integrate each one of them, including:
Troubleshooting
Relationships and/or uploads are not populating
If you are using relationships or uploads in your front-end application, and your front-end application runs on a different domain than your Payload server, you may need to configure CORS to allow requests to be made between the two domains. This includes sites that are running on a different port or subdomain. Similarly, if you are protecting resources behind user authentication, you may also need to configure CSRF to allow cookies to be sent between the two domains. For example:
Relationships and/or uploads disappear after editing a document
It is possible that either you are setting an improper depth
in your initial request and/or your useLivePreview
hook, or they're mismatched. Ensure that the depth
parameter is set to the correct value, and that it matches exactly in both places. For example:
Iframe refuses to connect
If your front-end application has set a Content Security Policy (CSP) that blocks the Admin Panel from loading your front-end application, the iframe will not be able to load your site. To resolve this, you can whitelist the Admin Panel's domain in your CSP by setting the frame-ancestors
directive: