> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

# Live preview - Live updates

> Learn how to set up live updates in live preview

## Overview

Live updates is an advanced [live preview](/tutorials/preview/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

> **Info**
>
> To enable live updates, it is required to set up [live preview](/tutorials/preview/live-preview) first.

### Implementation with Vanilla JS and React

1. Initialize the [live preview SDK](https://github.com/contentful/live-preview) with the live preview provider.

#### Vanilla JS

```javascript
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'])
});
```

#### React

```ts
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>
);
```

> **Info**
>
> See also: [Provider configuration](/tutorials/preview/live-updates#provider-configuration).

2. Import the `useContentfulLiveUpdates` hook and pass the **original and full (untransformed)** API response data to it. If you're using inspector mode with Content Source Maps, make sure to pass the encoded result to `useContentfulLiveUpdates`. The hook then returns the live updated data in real time. See an example in the code snippet below:

> **Info**
>
> For live updates when using GraphQL, it is necessary to fetch `sys.id` and `__typename` in your query.

#### Vanilla JS

```js
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.
});
```

#### React

```ts
import { useContentfulLiveUpdates } from '@contentful/live-preview/react';

const updatedEntries = useContentfulLiveUpdates(entries);
```

### Implementation with Next.js app router

1. Create a Next.js client component where you initialize the `ContentfulLivePreviewProvider` from the SDK.

```javascript
"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:

```javascript
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](https://github.com/contentful/live-preview/tree/main/examples) on Github.

> **Info**
>
> See also: [Provider configuration](/tutorials/preview/live-updates#provider-configuration).

2. The `useContentfulLiveUpdates` hook needs to be called in a client component:

```js
"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:

```js
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:

```ts
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');
}
```

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](https://github.com/contentful/live-preview/tree/main/examples) on Github.

## Provider configuration

The `ContentfulLivePreviewProvider` accepts parameters that allow you to customize your live preview SDK experience. The following options are available:

```jsx
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](/references/content-delivery-api/overview) 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 work 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. **Exception**: If you're using inspector mode with Content Source Maps, pass the encoded result into `useContentfulLiveUpdates`.
* [Contentful Functions](/extensibility/app-framework/functions) that resolve data in the delivery context are not compatible with live updates.