What you'll learn
  • what changed in the Next.js SDK in Webiny 6.5
  • how to upgrade a frontend built on the 6.4 starter kit
  • how to add the Webiny SDK to a Next.js app that has never used it
  • which AI prompt to give your coding agent for each case

This guide covers your Next.js frontend. Upgrade your Webiny project first, following Upgrade from 6.4.x to 6.5.0.

Overview
anchor

Webiny 6.5 replaces the two packages the Next.js starter kit used before, @webiny/website-builder-nextjs and @webiny/sdk, with a single package, @webiny/sdk-nextjs. One sdk object now covers Website Builder pages, Headless CMS entries, languages, file manager, and tenant manager. The same package also powers Headless CMS live preview.

What you need to do depends on your frontend:

Each section gives you two ways to do the same work. Pick one:

  • Use an AI agent. Paste the prompt into Claude Code, Cursor, Copilot, or a similar agent from your Next.js project root. The prompts are self-contained: they describe the target setup, point the agent at the reference starter kit, and say what to leave alone.
  • Make the changes yourself. Follow the steps under the prompt. They list the same changes the prompt makes, so they also work as a checklist for reviewing what the agent did.

The reference implementation is the starter-kit-6.5.x branch of webiny/website-builder-nextjsexternal link.

File Inputs
anchor

6.5 adds crops, focal points, and alt text to images picked in a createFileInput() input. The stored value keeps every field 6.4 had, so existing components keep working, and gains these:

FieldHolds
image.width, image.heightThe image’s intrinsic size, the same values as width/height
image.crop, image.focalPoint, image.alt, image.captionEdits made in the 6.5 editor
urlsrc with the crop applied

The root mimeType, width, and height stay for backwards compatibility. New code should read image.width and image.height.

This has two consequences:

  • A frontend on 6.4 packages reads src, so it shows the original, uncropped image and ignores alt text and focal points set in the 6.5 editor. Nothing breaks.
  • Values saved in 6.4 have no image or url until an editor picks or edits the image in 6.5. To read old and new values the same way on 6.5 packages, use normalizeToAsset(). It fills in image and url for values saved in 6.4:

Use asset.url rather than asset.src, so crops set in the editor show up.

When to Upgrade
anchor

Keep your frontend’s Webiny packages on the same version as your Webiny project. The quickest way to get there is to bump @webiny/website-builder-nextjs and @webiny/sdk to 6.5.0. That needs no code changes. The API calls, the editor connection, and the exported functions are the same as in 6.4.

Moving to @webiny/sdk-nextjs is a larger change that you can make later. It’s what gives your frontend Headless CMS content, CMS live preview, and content entry inputs.

A frontend that stays on 6.4 packages also keeps working against a 6.5 API. It shows images uncropped, because crops set in the 6.5 editor need 6.5 packages. That helps when the frontends aren’t yours to deploy, for example when each of your clients hosts their own site. Upgrade Webiny first, then give each client this page.

Upgrade Order
anchor

Upgrade Webiny first, then the frontend:

  • Upgrade and deploy your Webiny project, following Upgrade from 6.4.x to 6.5.0. A frontend on 6.4 packages keeps working against the 6.5 API.
  • Bump the frontend packages to 6.5.0 when it suits you. To show crops, focal points, and alt text from the 6.5 editor, read file inputs through normalizeToAsset(). See File Inputs.
  • Move to @webiny/sdk-nextjs whenever it suits you.

Don’t upgrade the frontend first. The 6.5 packages rely on API features that a 6.4 project doesn’t have.

What Changed
anchor

Area6.4 starter kit6.5 starter kit
Packages@webiny/website-builder-nextjs and @webiny/sdk@webiny/sdk-nextjs
SDK objectcontentSdk for pages, a separate new Webiny() client for everything elseOne sdk object: sdk.wb, sdk.cms, sdk.languages, and so on
InitializationcontentSdk.init({ apiKey, apiHost, apiTenant, preview, theme }, callback)sdk.init({ endpoint, token, tenant, preview, wb: { theme, componentGroups } })
Return valuescontentSdk.getPage() returns the page or nullsdk.wb.getPage() returns a Result
Component groupsregisterComponentGroup() calls in a callbackcomponentGroups array passed to sdk.init()
Component registrationcreateComponent()createWbComponent() (createComponent() still works, it’s the same function)
Environment variablesNEXT_PUBLIC_WEBSITE_BUILDER_API_KEY, _API_HOST, _API_TENANT, _ADMIN_HOSTNEXT_PUBLIC_WEBINY_API_KEY, _API_HOST, _API_TENANT, _ADMIN_HOST
API key“Website Builder” (Website Builder read only)“Frontend Integration” (Website Builder, Headless CMS, and languages read)
Project layoutEverything under src/Files at the project root (app/, sdk/, theme/, …)

The rest works the same way as before: the middleware that handles draft mode, tenants, and redirects, the /api/preview route, the DocumentRenderer wrapper, and the theme files.

API Key and Environment Variables
anchor

The 6.5 starter kit reads NEXT_PUBLIC_WEBINY_* variables. Where you get the values depends on when your Webiny project was first deployed.

  • Deployed on 6.5 or later. Webiny created a “Frontend Integration” API key for you. The Configure Frontend dialog (Dev Tools menu in Admin) shows the key and the NEXT_PUBLIC_WEBINY_* variables. Copy them as they are.
  • Upgraded from 6.4. The project has the older “Website Builder” key and no “Frontend Integration” key. The dialog falls back to the old key and shows the old NEXT_PUBLIC_WEBSITE_BUILDER_* names. Rename the variables to NEXT_PUBLIC_WEBINY_* and keep the values.

The old “Website Builder” key can only read Website Builder data. That covers rendering pages and redirects. To use Headless CMS content, content entry inputs, or CMS live preview in your frontend, the key also needs read access to Headless CMS. Edit it under Settings → Access Management → API Keys, or create a new read-only key with Website Builder, Headless CMS, and Languages read access.

Upgrade a 6.4 Starter Kit Project
anchor

Use this if your app started from the Next.js starter kit before Webiny 6.5. You can tell by the imports: @webiny/website-builder-nextjs and a src/contentSdk/ folder.

Option 1: Use an AI Agent
anchor

Paste this prompt into your agent. It makes every change listed in Option 2, so you don’t need to do those steps as well.

Option 2: Make the Changes Yourself
anchor

Use these steps if you’re not using an AI agent. If you ran the prompt, use them to review the agent’s changes.

  • Replace @webiny/website-builder-nextjs and @webiny/sdk with @webiny/sdk-nextjs@~6.5.0 in package.json, and update every import. The webpack helper moves to @webiny/sdk-nextjs/webpack.js, the Lexical styles to @webiny/sdk-nextjs/lexical.css, and the Language type to @webiny/sdk-nextjs.
  • Replace contentSdk.init() with sdk.init(). The config keys change (apiHost to endpoint, apiKey to token, apiTenant to tenant), and theme moves under wb.
  • Turn your registerComponentGroup() calls into a componentGroups array and pass it as wb.componentGroups.
  • Delete the separate new Webiny() client and use the matching property on sdk instead (sdk.languages, sdk.cms, and so on).
  • Update page, page list, and redirect calls to sdk.wb.* and handle the returned Result.
  • Call your SDK initializer at the top of every server entry point (page components, generateMetadata, generateStaticParams, route handlers) before any sdk.* call. In 6.4 the separate new Webiny() client was ready as soon as its module loaded. In 6.5, sdk.languages and the other namespaces throw until sdk.init() has run, so a call that runs in parallel with a helper that initializes the SDK fails on the first request after a cold start.
  • Read file inputs through normalizeToAsset(), so crops, focal points, and alt text from the 6.5 editor show up. See File Inputs.
  • Rename the environment variables in .env, next.config.ts, the SDK initializer, and your hosting provider.
  • In next.config.ts, add "pino-pretty": "commonjs pino-pretty" next to the existing thread-stream entry in config.externals.

Here’s the SDK initializer before and after:

src/contentSdk/initializeContentSdk.ts
sdk/initializeSdk.ts

And fetching a page:

Add the SDK to an Existing Next.js App
anchor

Use this if you have a Next.js App Router app that has never used the Webiny SDK and you want to render Website Builder pages in it. Your routes, layouts, and components stay. The SDK adds a route for Webiny pages and the plumbing the editor needs to load your app in an iframe.

Option 1: Use an AI Agent
anchor

Paste this prompt into your agent. It makes every change listed in Option 2, so you don’t need to do those steps as well.

Before running the prompt, decide where Webiny pages should live and replace <PAGES_ROUTE> with it. Use / if Webiny should own every URL that your app doesn’t already handle, or a prefix such as /pages to keep Webiny pages in one section.

Option 2: Make the Changes Yourself
anchor

Use these steps if you’re not using an AI agent. If you ran the prompt, use them to review the agent’s changes. Each item below corresponds to a file in the starter kitexternal link. Copy it and adapt it to your app.

  • package.json. Install @webiny/sdk-nextjs@~6.5.0. It requires Next.js 15 and React 19. Next.js 16 isn’t supported yet.
  • .env. Add the NEXT_PUBLIC_WEBINY_* variables from the Configure Frontend dialog.
  • sdk/. Add initializeSdk.ts, SdkInitializer.ts, getTenant.ts, and groups.ts.
  • theme/. Add theme.css and theme.ts. The editor reads colors, fonts, and typography styles from createTheme(), so base them on your existing design.
  • next.config.ts. Add the theme CSS webpack plugins, the frame-ancestors CSP header, and the image remote pattern. Without the CSP header, the browser refuses to load your app inside the Webiny editor.
  • middleware.ts. Add draft mode handling, the tenant header, and redirect lookup. Merge it with your middleware if you already have one.
  • app/api/preview/route.ts and app/api/redirects/route.ts. Add both routes.
  • A page route. Add a catch-all route that fetches the page with sdk.wb.getPage() and renders it with DocumentRenderer.
  • Root layout. Initialize the SDK, inject the theme CSS, and render SdkInitializer.
  • editorComponents/. Register the components editors can use. See Create Custom Component.

Then set Frontend Domain in the Configure Frontend dialog to your app’s URL, create a page in Website Builder → Pages, and publish it.

Headless CMS Content and Live Preview
anchor

The same sdk object reads Headless CMS content, so you don’t need a second client:

To show an entry in the Headless CMS live preview pane, set previewPath in the model settings. In a code-defined model, use .settings({ previewPath: "/articles/{values.slug}" }). The pane loads <Frontend Domain>/articles/preview with wb.editing=true, wb.type=entry, and wb.id=<entry ID> query parameters. Your app needs a route at that path that renders the entry with EntryRenderer. The app/(site)/articles/ folder in the starter kit shows both the published route and the preview route.

For CMS features, the API key needs Headless CMS read access. See API Key and Environment Variables.