Readme · Guides · Reference · Contributing
Reference implementation for @contentful/optimization-nextjs in a Next.js Pages Router
application. Pages call createRequestHandoff() from getServerSideProps, pass the returned
browser handoff through pageProps, and mount the bound Pages Router root and route tracker once in
pages/_app.tsx. The public permutation route uses createPublicPermutationHandoff() from
getStaticProps with ISR.
The implementation binds OptimizationRoot, OptimizedEntry, and NextPagesAutoPageTracker once
in @/lib/optimization with bindNextjsPagesRouterOptimization(). Browser runtime imports use
Next.js SDK package subpaths. The package root is not imported:
@contentful/optimization-nextjs/pages-router in @/lib/optimization for the bound component
binding and route tracker@contentful/optimization-nextjs/pages-router/server in @/lib/optimization-server for
getServerSideProps request handoff@contentful/optimization-nextjs/client for browser hooks and providers@contentful/optimization-nextjs/api-schemas in components that need SDK schema guardsUse this implementation when you need a Pages Router example where getServerSideProps fetches
Contentful entries, prepares Optimization state, and lets the browser SDK continue from that state
after hydration. It covers:
bindNextjsPagesRouterOptimization()createRequestHandoff() through pagePropsgetStaticProps with fallback: false and revalidate: 60NextPagesAutoPageTrackerOptimizedEntryinitialPageEvent ownership from the handoff so the browser skips only when the server request
accepted the first page eventPUBLIC_OPTIMIZATION_ENABLE_PREVIEW_PANELThe implementation defines one locale at appConfig.locale, passes it to the Next.js SDK server
helper, uses it for event context, and passes it directly to Contentful CDA fetches. Do not use
contentful.js withAllLocales or raw CDA locale=*; SDK entry resolution expects direct
single-locale fields such as fields.nt_experiences and fields.nt_variants.
Use getServerSideProps for pages that need server-personalized first paint. It fetches entries,
calls the Pages Router Optimization helper, and returns both through props. pages/_app.tsx
passes pageProps.contentfulOptimization.handoff to the bound OptimizationRoot with the current
routeKey and buildPagePayload; the handoff carries the first-page-event decision so the browser
does not duplicate an accepted server page event.
Use getStaticProps and getStaticPaths for finite public personalization permutations. The
/selection-handoff/[segment] route builds a public-permutation handoff with the SDK helper,
renders resolved entries into raw HTML with tracking attributes, and revalidates every 60 seconds.
.nvmrc)Run these commands from the monorepo root:
pnpm install
pnpm build:pkgs
pnpm implementation:run -- nextjs-sdk_pages-router implementation:install
test -f implementations/nextjs-sdk_pages-router/.env || cp implementations/nextjs-sdk_pages-router/.env.example implementations/nextjs-sdk_pages-router/.env
The .env.example values are mock-safe defaults for the shared local mock API. Provide live
Contentful and Optimization values only when testing against real services.
PUBLIC_OPTIMIZATION_STATIC_HANDOFF_MISSING_ENTRY controls static public handoff routes when a
required Contentful entry is missing: keep the default throw to fail the route, or use not-found
when you intentionally want those routes to return a 404.
Run these commands from the monorepo root:
pnpm implementation:run -- nextjs-sdk_pages-router dev
pnpm implementation:run -- nextjs-sdk_pages-router build
pnpm implementation:run -- nextjs-sdk_pages-router typecheck
pnpm implementation:run -- nextjs-sdk_pages-router lint
The development server runs on http://localhost:3001.
For production-style local serving with PM2-managed mock and app processes:
pnpm implementation:run -- nextjs-sdk_pages-router serve
pnpm implementation:run -- nextjs-sdk_pages-router serve:stop
Run the full E2E setup and test suite from the monorepo root:
pnpm setup:e2e:nextjs-sdk_pages-router
pnpm test:e2e:nextjs-sdk_pages-router
The E2E suite reuses the shared lib/e2e-web browser scenarios for CSR, hydration, and SSR
first-paint behavior under the Pages Router configuration.
Use Playwright UI or codegen when needed:
pnpm implementation:run -- nextjs-sdk_pages-router test:e2e:ui
pnpm implementation:run -- nextjs-sdk_pages-router test:e2e:codegen