Skip to Content
Delmare Digital

Upgrade guide

What each breaking or security release of payload-puck asks of you, oldest step first.

This page lists what each breaking or security release asks of you. Releases not listed need nothing beyond the version bump. If you are skipping versions, apply every step between your version and the latest, oldest first. Full detail for every release is in the changelog.

0.11.0: anonymous reads see published pages only

Security fix. The generated pages collection previously defaulted to unrestricted reads. Anonymous requests to GET /api/pages?draft=true or /api/pages/:id?draft=true could retrieve unpublished content. Its default read access now returns { _status: { equals: 'published' } } for anonymous callers and true for authenticated Payload users. Published frontend pages remain readable without signing in; anonymous draft previews now require authentication or an explicit access rule. With drafts turned off (collectionOverrides: { versions: { drafts: false } }) there is no _status field, so anonymous reads stay allowed and nothing changes.

Your access.read or collectionOverrides.access.read still wins. Collections you define yourself keep their existing access rules. Server-side Local API calls still default to bypassing access: use overrideAccess: false to enforce collection access, or explicitly filter _status to published in public queries.

To explicitly restore the old behaviour, including anonymous access to unpublished content:

src/payload.config.ts
createPuckPlugin({
  access: {
    read: () => true,
  },
})

0.10.3: integrations

No action needed. mergeConfigs / extendConfig, PuckConfigProvider and PuckEditor accept integrations: bundles of components, categories and editor plugins from other packages. Nothing changes if you don't use them. See Integrations.

0.10.2: security fix, full-screen editor

Upgrade recommended. The admin editor view at /admin/puck-editor/:collection/:id read the page's draft through the Local API without an access posture, so any signed-in admin user could open the editor for a page the collection's read access denies them and see its draft content. Saving was never affected. The view now reads as the signed-in user.

Two behaviour changes come with it:

  • The admin editor is full-screen. It no longer renders inside Payload's nav and header, and fills the viewport. It stays under /admin, so session and access handling are unchanged, and the editor's Back button returns to the document. "Edit with Puck" links need no changes.
  • The canvas no longer inherits the admin page's CSS. If your preview relied on a stylesheet loaded into the admin page rather than listed in editorStylesheets, add it to editorStylesheets.

0.10.0: Puck 0.24 (breaking)

  • @puckeditor/core ≥ 0.24.0. Run the install below. The built-in components now arrange their sidebar fields in General / Style / Layout tabs, and the action bar shows a drag handle (turn it off with dnd={{ enableDragHandle: false }} on PuckEditor). Saved page data is unchanged.
  • Custom component configs built by spreading a built-in one keep its tab layout; fields you add appear in the first tab. To place them yourself, set your own renderFields with createFieldLayout(), or renderFields: undefined for Puck's default flat list.
npm i @puckeditor/core@^0.24.0

0.9.5: homepage uniqueness

Upgrade from 0.9.4. 0.9.4 let a draft marked as homepage be published without the uniqueness check, and let live writes with no _status skip it, which could leave two published homepages. If a site saw a draft homepage published on 0.9.4, check for more than one page with isHomepage set and unset the extra. Earlier versions are not affected.

0.9.3: security fix

No action needed; upgrade. On the built-in /api/puck/* update endpoint, a homepage swap could clear the site's current homepage on behalf of a user who was not allowed to make the edit (GHSA-cphw-vvv5-c8p7). The swap is now authorized first, and both writes run in one transaction.

0.9.1: pages collection write defaults

The generated pages collection used to default create, update and delete to allow-all, so anonymous callers could write pages through Payload's REST and GraphQL APIs if you passed no access option. Since 0.9.1, writes default to any authenticated user. Anonymous reads are restricted to published pages from 0.11.0.

  • Already pass access? Nothing to do. Anything you pass still wins.
  • Relied on the default? Decide who may write pages and say so. If any untrusted users can sign in (public sign-up, customers), "authenticated" is not enough:
src/payload.config.ts
createPuckPlugin({
  access: {
    create: ({ req }) => req.user?.role === 'admin',
    update: ({ req }) => req.user?.role === 'admin',
    delete: ({ req }) => req.user?.role === 'admin',
  },
})

0.9.2 added access.readVersions and stopped collectionOverrides from replacing these merged access rules. See Plugin options.

0.9.0: standalone route factories (breaking, security)

Only affects apps that wired the route factories themselves (createPuckApiRoutes, createPuckApiRoutesWithId, createPuckApiRoutesVersions from /api, or createPromptApiRoutes from /ai). The built-in /api/puck/* endpoints are unchanged.

These factories now enforce Payload collection access control (GHSA-957g-hmmp-rchg), so they need to know which Payload user a request acts as:

Build authenticate on payload.auth({ headers: request.headers }). This works for every auth system, including Better Auth, Clerk and custom strategies.

Do not return your auth library's session user, and do not map a session back to a user by email.

Expect denials as 403 rather than 500, and check that any access rule reading request headers still behaves as intended, since headers are now forwarded.

The full recipe, the toPayloadUser escape hatch, fail-closed behaviour and the emergency opt-out are in Custom API routes.

0.8.0: editor stylesheet (breaking)

Editor CSS is now built by your app, not by this plugin. This fixes the editor rendering unstyled in production on Next.js 16, where Turbopack never ran the webpack plugin that produced the old file.

Add a build:puck-css step with Tailwind's CLI and gitignore its output, as in Editor stylesheet.

Replace editorStylesheet, editorStylesheetCompiled and editorStylesheetUrls with a single editorStylesheets array of URLs.

Remove the withPuckCSS import and wrapper from next.config.

Drop any editorStylesheets prop on PuckConfigProvider; the plugin passes it through automatically.

Remove postcss and postcss-load-config if you installed them only for this plugin.

src/payload.config.ts
// before
createPuckPlugin({
  editorStylesheet: 'src/app/(frontend)/globals.css',
  editorStylesheetCompiled: '/puck-editor-styles.css',
  editorStylesheetUrls: ['https://fonts.googleapis.com/css2?family=Inter'],
})

// after
createPuckPlugin({
  editorStylesheets: ['/puck-editor-styles.css', 'https://fonts.googleapis.com/css2?family=Inter'],
})

0.7.0: version floors (breaking)

  • @puckeditor/core ≥ 0.23.0. Puck 0.23 ships a rewritten drag-and-drop engine and a redesigned outline, so the editor looks and feels different even though no API you call changed. Worth a pass through your editor after upgrading.
  • Node ≥ 20.9.0. Node 18 is no longer supported.
npm i @puckeditor/core@^0.23.0
Edit this page on GitHub

On this page