storyblok-preview
Run Storyblok live preview in a Next.js storefront that reads its content through a GraphQL gateway.
Get started
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/storyblok-preview next react react-domRequirements3
next>=16.2.11 <17react>=19react-dom>=19Wrap your app in
ContentPreviewProvider. Setup lists its props.
Then render it on a page:
// app/api/preview/route.tsimport { createPreviewHandler } from "@evolve-storefront/storyblok-preview/api-route";
export const GET = createPreviewHandler({ previewSecret: process.env.CMS_PREVIEW_SECRET ?? "", previewToken: process.env.STORYBLOK_PREVIEW_TOKEN ?? "", 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 Storyblok's preview URL points at.
import { createPreviewHandler } from "@evolve-storefront/storyblok-preview/api-route";function createPreviewHandler( options: HandlerOptions,): (request: Request) => Promise<Response>| Option | Type | Description |
|---|---|---|
defaultLocale | string | |
previewSecret | string | |
previewToken | string | |
localePrefix | Record<string, string> |
Returns (request: Request) => Promise<Response>
storyblokDataAttributesThese data attributes are used by the Storyblok preview functionality to make the component selectable.
import { storyblokDataAttributes } from "@evolve-storefront/storyblok-preview/component";The blok.id is the uid of the blok.
function storyblokDataAttributes( blok: ComponentFragment,): { "data-component-id": string; "data-component-type": string }| Option | Type | Description |
|---|---|---|
__typename | string | |
id | string |
Returns { "data-component-id": string; "data-component-type": string }
getPreviewIDParses the draft cookie and returns the story data.
import { getPreviewID } from "@evolve-storefront/storyblok-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 Storyblok editor sends an update through an iframe postmessage.
import { setPreviewConfigCookie } from "@evolve-storefront/storyblok-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>| Option | Type | Description |
|---|---|---|
previewID | string |
Returns Promise<void>
More in this package
- Setup and server: what the package needs in your project.

