Live preview - Live updates
Table of contents
Overview
Live updates is an advanced live preview feature that allows you to preview your changes without clicking the "Refresh preview" button. Whenever content is updated, the changes are immediately displayed in the live preview pane.
Setup
Implementation with Vanilla JS and React
- Initialize the live preview SDK with the live preview provider.
import { ContentfulLivePreview } from '@contentful/live-preview';
ContentfulLivePreview.init({
locale: 'en-US', // This is required and allows you to set the locale once and have it reused throughout the preview
enableInspectorMode: false, // This allows you to toggle the inspector mode which is on by default
enableLiveUpdates: false, // This allows you to toggle the live updates which is on by default
debugMode: false, // This allows you to toggle the debug mode which is off by default
targetOrigin: 'https://app.contentful.com', // This allows you to configure the allowed host of the live preview (default: ['https://app.contentful.com', 'https://app.eu.contentful.com'])
});
import { ContentfulLivePreviewProvider } from "@contentful/live-preview/react";
const App = ({ Component, pageProps }) => (
<ContentfulLivePreviewProvider
locale="en-US" // This is required and allows you to set the locale once and have it reused throughout the preview
enableInspectorMode // This allows you to toggle the inspector mode which is on by default
enableLiveUpdates // This allows you to toggle the live updates which is on by default
debugMode // This allows you to toggle the debug mode which is off by default
targetOrigin="https://app.contentful.com" // This allows you to configure the allowed host of the live preview (default: ['https://app.contentful.com', 'https://app.eu.contentful.com'])
>
<Component {...pageProps} />
</ContentfulLivePreviewProvider>
);
- Import the
useContentfulLiveUpdates
hook and pass the original and full (untransformed) API response data to it. The hook then returns the live updated data in real time. See an example in the code snippet below:
sys.id
and __typename
in your query.
import { ContentfulLivePreview } from '@contentful/live-preview';
/**
* Subscribe to data changes from the Editor, returns a function to unsubscribe
* Will be called once initially for the restored data
*/
const unsubscribe = ContentfulLivePreview.subscribe({
data, //the JSON response from the CPA for an entry/asset or an array of entries (or assets)
locale,
callback, //is a function to be called when the entry/asset is updated in Contentful to tell the frontend to update the preview. This callback is what makes the frontend update instantaneously when typing in a field in the editor.
});
import { useContentfulLiveUpdates } from '@contentful/live-preview/react';
const updatedEntries = useContentfulLiveUpdates(entries);
Implementation with Next.js app router
- Create a Next.js client component where you initialize the
ContentfulLivePreviewProvider
from the SDK.
"use client";
import { ContentfulLivePreviewInitConfig } from "@contentful/live-preview";
import { ContentfulLivePreviewProvider } from "@contentful/live-preview/react";
import { PropsWithChildren } from "react";
export function ContentfulPreviewProvider({
children,
...props
}: PropsWithChildren<ContentfulLivePreviewInitConfig>) {
return (
<ContentfulLivePreviewProvider {...props}>
{children}
</ContentfulLivePreviewProvider>
);
}
Once the provider is set up in the client component, you can wrap your server component app with it:
import { ContentfulPreviewProvider } from "../components/contentful-preview-provider";
export default function Home() {
const { isEnabled } = draftMode();
return (
<ContentfulLivePreviewProvider
locale="en-US" // This is required and allows you to set the locale once and have it reused throughout the preview
enableInspectorMode // This allows you to toggle the inspector mode which is on by default
enableLiveUpdates // This allows you to toggle the live updates which is on by default
debugMode // This allows you to toggle the debug mode which is off by default
targetOrigin="https://app.contentful.com" // This allows you to configure the allowed host of the live preview (default: ['https://app.contentful.com', 'https://app.eu.contentful.com'])
>
<main>...</main>
</ContentfulLivePreviewProvider>
);
}
For a full example visit the examples directory on Github.
- The
useContentfulLiveUpdates
hook needs to be called in a client component:
"use client";
import { useContentfulLiveUpdates } from "@contentful/live-preview/react";
// entry has been fetched in a Server Component higher up the tree and passed down via props
export const Renderer = ({ entry }) => {
const updatedEntry = useContentfulLiveUpdates(entry);
return (
<>
<h1>{updatedEntry.fields.title}</h1>
</>
);
};
I don't want to use any client components
For customers who prefer not to use client components in Next.js, we recommend implementing a lightweight JavaScript script. This script is designed to trigger a revalidation process via a specified endpoint whenever changes are saved in Contentful, and then it automatically reloads the iframe. Simply place the script in the public folder:
import { ContentfulLivePreview } from '@contentful/live-preview';
ContentfulLivePreview.init({
locale: 'en-US',
debugMode: true,
enableLiveUpdates: true,
});
ContentfulLivePreview.subscribe('save', {
callback: async () => {
const pathname = window.location.pathname;
await fetch(`/api/revalidate?pathname=${pathname}`);
window.location.reload();
},
});
The revalidation endpoint located in app/revalidate/route.ts
triggers the revalidation of a specific path based on a query string parameter (pathname) from the request URL:
import { revalidatePath } from 'next/cache';
function getQSParamFromURL(key: string, url: string): string | null {
if (!url) return '';
const search = new URL(url).search;
const urlParams = new URLSearchParams(search);
return urlParams.get(key);
}
export async function GET(request: Request) {
const path = getQSParamFromURL('pathname', request.url);
if (path) {
revalidatePath(path);
}
return new Response('OK');
}
A limitation of the reload script with the revalidation endpoint is that content must be tagged with inspector mode. This ensures that the page doesn't reload unnecessarily when updates are made to fields not currently displayed. For a full example visit the examples directory on Github.
Provider configuration
The ContentfulLivePreviewProvider
accepts parameters that allow you to customize your live preview SDK experience. The following options are available:
import { ContentfulLivePreviewProvider } from '@contentful/live-preview/react';
<ContentfulLivePreviewProvider
locale="set-your-locale-here" // Required: allows you to set the locale once and have it reused throughout the preview.
enableInspectorMode={false} // Optional: allows you to toggle inspector mode which is on by default.
enableLiveUpdates={false} // Optional: allows you to toggle live updates which are on by default.
targetOrigin="https://app.contentful.com" // Optional: allows you to configure the allowed host(s) of live preview (default: ['https://app.contentful.com', 'https://app.eu.contentful.com'])
debugMode={false} // Optional: allows you to toggle debug mode which is off by default.
>
To optimize non-preview websites, it is advisable to disable live preview functionality by setting both enableInspectorMode
and enableLiveUpdates
to "false". By doing so, any specific data related to live preview, such as data-attributes, is removed.
Known issues and limitations
- GraphQL filters (e.g. filters in the Array field type) or filtering using the select query parameter on the Content Preview API (CPA).
- We currently do not support multiple locales within a single GraphQL query or a single CPA response. Therefore, the
withAllLocales
chain modifier of the JS Client SDK is not supported. - Live updates works only with untransformed data. Ensure that the response from the CPA or GraphQL is provided to the hook in its full and original form, with any potential transformations applied afterwards.
- Cross-space content has no support with live updates. We only support removing or resorting resource links.