Skip to content

contentful-preview

@evolve-storefront/contentful-preview ยท v1.0.0

Run Contentful live preview in a Next.js storefront that reads its content through a GraphQL gateway.

Get started

  1. Install the package with the peer dependencies it needs. It comes from the Evolve registry, which needs a one-time sign-in.

    pnpm add @evolve-storefront/contentful-preview next react react-dom
    Requirements3
    next>=16.2.11 <17
    react>=19
    react-dom>=19
  2. Wrap your app in ContentPreviewProvider. Setup lists its props.

Then render it on a page:

// app/api/preview/route.ts
import { createPreviewHandler } from "@evolve-storefront/contentful-preview/api-route";
export const GET = createPreviewHandler({
previewSecret: process.env.CMS_PREVIEW_SECRET ?? "",
defaultLocale: "en",
// Where each locale's pages live, so the preview lands on the right one.
localePrefix: { en: "/en", nl: "/nl" },
});

Functions

createPreviewHandlerCreates the Next.js route handler that a Contentful preview URL points at.
import { createPreviewHandler } from "@evolve-storefront/contentful-preview/api-route";
function createPreviewHandler(
options: HandlerOptions,
): (request: Request) => Promise<Response>
OptionTypeDescription
defaultLocalestring
previewSecretstring
localePrefixRecord<string, string>

Returns (request: Request) => Promise<Response>

contentfulDataAttributesThe attributes a block needs for Contentful's inspector to select it.
import { contentfulDataAttributes } from "@evolve-storefront/contentful-preview/component";

Deliberately none. Contentful encodes them in the content itself through sourcemaps โ€” hidden unicode inside the strings โ€” so the inspector finds a block without the markup carrying anything. It exists so a project can wrap its registry the same way for either CMS and swap one import; Storyblok's returns real attributes.

function contentfulDataAttributes(
_block: ComponentFragment,
): Record<string, string>
OptionTypeDescription
__typenamestring
idstring

Returns Record<string, string>

getPreviewIDParses the draft cookie and returns the story data.
import { getPreviewID } from "@evolve-storefront/contentful-preview/server";

Note: this function is async because it's run in "use server"; mode.

function getPreviewID(): Promise<string | undefined>

Returns Promise<string | undefined>

setPreviewConfigCookieThis function is called when the Contentful editor sends an update through an iframe postmessage.
import { setPreviewConfigCookie } from "@evolve-storefront/contentful-preview/server";

Because we are using server components, the components will not rerender with a useState hook for a story. Instead, we update a cookie with the new story data and revalidate the current route. The page then gets rendered again with the new data not coming from the API but from the cookie instead.

function setPreviewConfigCookie(cfg: PreviewConfig): Promise<void>
OptionTypeDescription
previewIDstring

Returns Promise<void>

More in this package