hasMany: true
relationships nested to an array (#12980) (0e8ac0b)where
query has no results (#12991) (fafaa04)If your project uses the local auth strategy with db-postgres
or db-sqlite
, a migration is required. This is due to a new security feature (enabled by default) that stores a unique auth session identifier in the database.
To opt out and continue using the previous behavior, you can disable the feature by setting auth.useSessions: false
in your users collection config.
For example:
// payload.config.ts
collections: [
{
slug: 'users',
auth: {
useSessions: false,
},
fields: [],
},
],
disableBulkEdit
(#12850) (a5ec55c)draft: true
(#12868) (bc9b501)hasMany: true
select field in a relationship (#12916) (b74969d)database/int.spec.ts
with postgres custom schema (#12922) (cf87871)database
integration tests with postgres (#12919) (886c07e)data
argument in afterChange
hook for collections and globals (#12756) (458a04b)where
by ID (#12804) (9943b35)default
queue by default, adds support for allQueues argument (#12799) (06ad171)mongoose
to 8.15.1
(#12755) (860e0b4)drizzle-kit@0.31.0
and drizzle-orm@0.43.1
(#12256) (7045182)bnBD
and bnIN
translation imports to camelCase (#12736) (08fbcb5)buildPath
property (#12741) (38652d7)in
query with null
(#12661) (c08cdff)plugin-nested-docs
(#12494) (5635ec5)payload migrate:create
(#12596) (12395e4)migrate:reset
executes in a wrong order (#12445) (1b1e36e)'
character (#12590) (6888f13)Folders allow you to organize your documents in a more manageable way. Now you can enable folders on a per-collection basis and from there start adding folders from within the admin panel (or via the API). Once you have folders enabled you can then start organizing. You can create folders and store documents across multiple collection types and then view them either in the collection "By Folder" or in the global "Browse by Folder" view.
https://github.com/user-attachments/assets/da1e0dec-abc7-4e5c-9241-3a733b2bfa0c
withoutEnlargement
on update (#12291) (1235a18)hidden: true
for virtual fields that have reference to a relationship field (#12219) (1f6efe9)limit
from nested querying (#12464) (230128b)localized
value (#12414) (219fd01)@payloadcms/drizzle
(#12428) (38029cd)draft: true
(#12387) (fd67d46)near
sort query properly for point fields (#12240) (58fc2f9)dbName
in arrays regression with long generated drizzle relation names (#12237) (5fce501)filterOptions: { id: { in: [] } }
(#12408) (8ebadd4)nextPage
and prevPage
are non nullable even though they can be null
sometimes (#12201) (3fb81ef)relationTo
as an array (#12289) (c08c707)select
(#12266) (564fdb0)count
crashes when query contains subqueries and doesn't return any rows (#12273) (4a56597)limit: 0
is passed (#12261) (27d644f)beforeDocumentControls
slot to allow custom component injection next to document controls (#12104) (d553069)showSaveDraftButton
option to show draft button with autosave enabled (#12150) (34ea6ec)version
when not selected (#12158) (6dc61ae)near
operator is used (#12185) (9955818)useAsTitle
virtual fields linked with a relationship field (#11805) (1c99f46)createSchemaGenerator
(#12043) (71e3c78)where
querying by join fields (#12075) (466dcd7)relationTo
with overrideAccess: false
(#11999) (b9ffbc6)dbName
is used (#11995) (09782be)file
field is only serialized at top-level for upload-enabled collections (#12074) (112e081)_payload
& field explanation (#12025) (83319be)dev:generate-types
(#11994) (97e2e77)password
field when using disableLocalStrategy: true
(#11893) (8ad22eb)ValidationError
error message when label
is a function (#11904) (dc793d1)doc
input for scheduled publish job if it's enabled only for globals (#11892) (760cfad)deleteOne
fails when the where
query does not resolve to any document (#11632) (4ebd3ce)migrationTableExists
doesn't check in the current transaction (#11910) (f310c90)draft: true
when querying joins (#11869) (e5690fc)clientUploads.routerInputConfig
to the handler (#11962) (8e93ad8)modifiedOnly
default to true
(#11794) (21f7ba7)Query Presets allow you to save and share filters, columns, and sort orders for your collections. This is useful for reusing common or complex filtering patterns and column configurations across your team. Query Presets are defined on the fly by the users of your app, rather than being hard coded into the Payload Config.
https://github.com/user-attachments/assets/1fe1155e-ae78-4f59-9138-af352762a1d5
This release bumps the peer dependency version of Next.js to 15.2.3
to address a security vulnerability. Next.js Blog post here for more detail. (PR #11823).
NOTE: This vulnerability does not affect any of the functionality of Payload, as the framework does not leverage anything affected in the vulnerability. This would only affect you if you've built additional functionality on top of Payload using additional Next.js middleware.
draft: true
when querying docs for the join field (#11763) (1b2b6a1)This release upgrades the lexical dependency from 0.27.1
to 0.28.0
.
If you installed lexical manually, update it to 0.28.0
. Installing lexical manually is not recommended, as it may break between updates, and our re-exported versions should be used. See the yellow banner box for details.
If you still encounter richtext-lexical errors, do the following, in this order:
node_modules
pnpm-lock.json
)pnpm install
)forceSelect
collection / global config property (#11627) (5e3d07b)id
to create operation data without custom IDs (#11709) (f442d22)select
& radio
field option labels accept JSX elements (#11658) (3c92fbd)useAsTitle
(#11707) (ef527fe)useDocumentInfo
(#11686) (ff2df62)We’ve introduced a new opt-in flag that can cut Payload’s compile times in half during development. To enable it, add the following to your next.config.js:
const nextConfig = {
// ...
}
-export default withPayload(nextConfig)
+export default withPayload(nextConfig, { devBundleServerPackages: false })
In some rare cases, you may see unexpected behavior if your project relies on server-only Payload dependencies being bundled during development. Because of this, we’ve made the feature opt-in for existing projects.
This release upgrades the lexical dependency from 0.21.0
to 0.27.1
. Alongside table improvements and bug fixes, this version bump lays the groundwork for frequently requested features like color pickers.
If you installed lexical manually, update it to 0.27.1
. Installing lexical manually is not recommended, as it may break between updates, and our re-exported versions should be used. See the yellow banner box for details.
If you still encounter richtext-lexical errors, do the following, in this order:
node_modules
pnpm-lock.json
)pnpm install
)payload-locked-documents
collection (#11624) (8f3d1bd)updateVersion
read result (#11589) (e9afb36)i18n
configuration (#11590) (5d65cb0)payload migrate:create
flags (#11592) (3de1636)disablePayloadAccessControl: true
(#11530) (5cc0e74)clientUploads
is not set (#11527) (e36ab6a)indexes
default value sanitization (#11534) (f0ea918)upload.formatOptions
set file types (#11505) (c417e3a)prefix
configured (#11436) (fc42c40)mongoose-aggregate-paginate-v2
with a custom implementation (#10936) (d4d2bf4)sharp
to be specified in payload config (#11470) (d57a786)create-payload-app@latest
instead of @beta
(#11451) (e055565)strict: true
and noUncheckedIndexedAccess: true
(#11444) (79a7b4a)select
query exists (#11400) (526e535)bin
configuration for custom scripts (#11294) (f779e48)hasNextPage
with polymorphic joins (#11394) (6b6c289)useAsTitle
field is undefined (#11338) (09ca514)DiscardWithoutSaving
modal styles (#11381) (7bb1c9d)configToJSONSchema
(#11342) (a13d4fe)JSON.parse(JSON.stringify)
copying of results (#11293) (1dc748d)rateLimit
option (#11291) (c517e7e)page
query parameter for joins
(#10998) (847d8d8)hideFileInputOnCreate
and hideRemoveFile
to collection upload
config (#11217) (daaaa5f)countDistinct
works correctly and achieve better performance when the query has table joins (#11208) (513ba63)admin.readOnly: true
is set (#11184) (b1734b0)res
parameter in login
and resetPassword
operations (#11268) (38c1c11)payload-types.ts
for all test suites (#11238) (117949b)select
type errors (#11235) (e78500f)locked-documents
type errors (#11223) (ee0ac7f)blockReferences
(#11195) (2ae670e)resource={null}
to Media
component (#11228) (64d0217)handler
does not accept array of functions anymore (#11110) (1f3ccb8)usePayloadAPI
hook to React Hooks documentation (#11079) (d56de79)BlockquoteFeature
name (#11078) (87ba7f7)createdAt
, updatedAt
and globalType
fields (#10938) (57143b3)hasMany: true
with autosave doesn't work properly (#11012) (3ad56cd)pnpm dev
defaults to the _community test suite (#11044) (49d94d5)create
access control is false
(#10954) (136c90c)@ts-ignore
in seed to allow initial build on vercel (#10889) (2043b4a)headersWithCors
(#10597) (be98eda)?locale=*
doesn't return full localized data (#10619) (7f8f2f0)minDistance
and maxDistance
in near
query (#10622) (46c1b37)all
operator (#10704) (d601300)handleError
(#10575) (9043b10)serverURL
and routes.api
(#10618) (5a95237)This release upgrades the lexical dependency from 0.20.0
to 0.21.0
. If you installed lexical manually, update it to 0.21.0
. Installing lexical manually is not recommended, as it may break between updates, and our re-exported versions should be used. See the yellow banner box for details.
If you still encounter richtext-lexical errors, delete node_modules
and your lockfile (e.g. pnpm-lock.json
), then reinstall (e.g. pnpm install
). Some package managers do not update the lexical peerdep automatically, likely due to a bug on their end.
Please upgrade to 3.17.1. In 3.17.0, you may encounter richtext-lexical dependency checker errors during development.
basePath
option (#10535) (04a8083)afterChange
(#10410) (1af7d87)uploads
collection edit view (#10426) (9701fc6)all
to the locale type definition in req (#10399) (eadce5e)withoutEnlargement
for undefined height
or width
(#10078) (d212733)maxDepth: 0
for join fields, improve join field JSDoc (#10336) (ba228dd)undefined
fallback for adapter.schemaName
in relationships migration (#10384) (1525cc6)cross-env
in the plugin template to achieve compatibility with Windows (#10390) (c1abd16)loggingLevels
is respected (#10308) (2e58a4a)defaultPopulate
on collections with uploads enabled (#10138) (d6d9edc)file:
url (#9311) (16c6abe)payload
usage from req
to avoid import payload
confusion (#10291) (76e4402)--example
CLI arg (#10172) (6b4842d)getLocalizedPaths
for blocks (#10187) (eff75f9)en
language is defined in i18n (#10181) (8debb68)collection
(#10182) (a0d8131)publishConfig
for the plugin template (#10196) (a5b9adc)Dockerfile
for the website template, use the LTS version for Node.js image (#10184) (5613a7e)next
to 15.1.3
in the monorepo (#10211) (7a4d53a)jsdocs for generated types, by using admin.description (#9917) (b330873)
db-postgres, db-sqlite: drizzle schema generation (#9953) (23f1ed4)
Full type safety on payload.drizzle with a single command
pnpm payload generate:db-schema
https://github.com/user-attachments/assets/96bddfe6-b598-42ae-8efd-eae7dab7a4e8
make req
partial and optional in DB / Local API operations (#9935) (0e5bda9)
db-postgres, db-sqlite: drizzle schema generation (#9953) (23f1ed4)
"for"
attribute for label (#10036) (97c120a)DATABASE_URI
env var from with-vercel-website
template .env.example (#10098) (52b1a9a)collectionsSchemaOptions
(#9885) (198763a)vercel-postgres
db types to use POSTGRES_URL
& updates .env.example
to use generic env var strings (#10027) (70666a0)select
query on upload fields with hasMany: true
(#10029) (2ee3e30)rows
for the textarea
field (#10031) (61c5e0d)req
to defaultValue
function arguments (#9937) (6dea111)pg
instead of @vercel/postgres
(#9771) (41167bf)localized
property from RowField
and CollapsibleField
(#9672) (c187bff)pagination: false
to REST / GraphQL (#9952) (b101fec)payload.db.upsert
inserts new rows instead of updating existing ones (#9916) (5e39634)readOnly
prop to email & username auth fields (#9938) (a582431)session
, db
in migrations to use the active transaction with the database directly (#9849) (b73fc58)where
in payload.jobs.run (#9877) (b1ef28d)suppressHydrationWarning
property to payload config admin options (#9867) (5223990)tstyche
(#9803) (f09ee0b)upgrade to React 19 stable and Next.js 15.0.4 (#9801) (8f3f449)
It is recommended to upgrade to React 19 stable and Next.js 15.0.4 in your existing project. The pnpm.overrides
and overrides
keys are not needed anymore!
To do that, change the following in your package.json
:
...
"dependencies": {
- "next": "15.0.3",
+ "next": "15.0.4",
- "react": "19.0.0-rc-66855b96-20241106",
- "react-dom": "19.0.0-rc-66855b96-20241106",
+ "react": "19.0.0",
+ "react-dom": "19.0.0",
...
},
"devDependencies": {
- "@types/react": "npm:types-react@19.0.0-rc.1",
- "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1".
+ "@types/react": "19.0.1",
+ "@types/react-dom": "19.0.1",
},
- "pnpm": {
- "overrides": {
- "@types/react": "npm:types-react@19.0.0-rc.1",
- "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
- }
- },
- "overrides": {
- "@types/react": "npm:types-react@19.0.0-rc.1",
- "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
- }
sanitizeSelectParam
, sanitizePopulateParam
, senitizeJoinParams
utils (#9777) (afd0b54)defaultPopulate
and populate
with nested to arrays/blocks properties (#9751) (7def6b7)getPayload
generate import map only when used in Payload Admin Panel (#9371) (d8f7034)mongoose
to 8.8.3
(#9747) (840dde2)select
query on select fields (#9607) (dff71ee).env.example
env vars along side .env
vars based on selected DB (#9757) (1aa23d3)auth.forgotPassword.expiration
prop (#9739) (c7218c0)beforeInput
& afterInput
props for arrays
, blocks
, collapsible
, group
, radio
, & relationship
fields. (#9674) (58b7415)doc
has the same value
but different relationTo
(#9616) (b896507)/access-control/overview
(#9619) (bc2d7c9)APIError
errors to sentry (#9595) (61a51ca)where
query paths from access result (#9349) (a9f511d)flattenedFields
collection/global property, remove deep copying in validateQueryPaths
(#9299) (cae300e)getMigrations
(#9330) (e176b8b)/payload-jobs/run
endpoint without workflows (#9509) (b96475b)deleteJobOnComplete
property for jobs works (#9283) (7eb388d)sanitizeRelationshipIDs
named tabs within tabs (#9400) (b5f89d5)hasMany: true
(#9464) (e5cc915)payload.collections
type (#9414) (91dcf6d)next@15.0.3
compatibillity for turbopack warnings patch (#9341) (f2205d1)This is a major release that includes a re-architecture of Payload from an Express + React Router SPA to the Next.js App Router + RSCs. In addition to this architectural change, we've also shipped a ton of large features, miscellaneous fixes, and DX improvements.
ui
, next
, translations
, and graphql
nodemon
hasMany
upload fields are now supported_rels
tablecount
, countVersions
, countGlobalVersions
, upsert
baseListFilter
function to allow enforced list view filters based on usert
function/access
permissions resultsreact-toastify
for sonner
virtual: true
This release includes breaking changes. In order to update from version 2 to 3, please review the migration docs.
strict: true
(#9281) (e40141b)sanitizeRelationshipIDs
with ref
being a non object (#9292) (665b353)removes unnecessary field styles from initial page response (#9286) (30947d2)
This only effects those who are importing Payload's field components
into your own Custom Components or front-end application. The width
prop no longer exists. It has been consolidated into the existing
style
prop. To migrate, simply move this prop as follows:
import { TextInput } from '@payloadcms/ui
export const MyCustomComponent = () => {
return (
<TextInput
- width="60%"
style={{
+ width: "60%,
}}
/>
)
}
getTableState
from join field on create (#9256) (ef2475d)proper casing for default root views (#9248) (ed21c1c)
Custom account
and dashboard
views now defined as lowercase in the
config.
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
components: {
// ...
views: {
// ...
- Account: ...
- Dashboard: ...
+ account: ...
+ dashboard: ...
},
},
},
})
richtext-lexical: significantly reduce lexical rerendering and amount of network requests from blocks (#9255) (35917c6)
The field RSC now provides an initial state for all lexical blocks. This completely obliterates any flashes and lexical block loading states when loading or saving a document.
This removes the feature.hooks.load
and feature.hooks.save
interfaces from custom lexical features, as they weren't used internally
and added unnecessary, additional overhead.
If you have custom features that use those, you can migrate to using normal payload hooks that run on the server instead of the client.
date-fns
to 4.1.0
(#9221) (6845878)db-mongodb: update mongoose to 8.8.1 (#9115) (7c6f419)
MongoDB projects need to run a migration after updating to this beta version, because all relationship IDs are now stored as ObjectID (as they should have always been saved) and we need to migrate your existing relationship data from string-based IDs to ObjectIDs.
To create this migration, run:
pnpm payload migrate:create --file @payloadcms/db-mongodb/relationships-v2-v3
And then run your migrations using:
pnpm payload migrate
In addition, if your project is heavily relying on using the Mongoose models directly, you may want to review the upgrade guides from v6 to v7 and v7 to v8, making adjustments as needed.
improve collection / global slugs type-safety in various places (#8311) (810c29b)
Improves type-safety of collection / global slugs by using CollectionSlug
/ UploadCollectionSlug
and GlobalSlug
types instead of string
in these places:
Adds UploadCollectionSlug
and TypedUploadCollection
utility types
This also changes how we suggest to add an upload collection to a cloud-storage adapter: Before:
azureStorage({
collections: {
[Media.slug]: true,
},
})
After:
azureStorage({
collections: {
media: true,
},
})
re-order DefaultCellComponentProps generics (#9207) (77c99c2)
Changes the order of the DefaultCellComponentProps
generic type,
allowing us to infer the type of cellData when a ClientField type is
passed as the first generic argument. You can override the cellData type
by passing the second generic.
Previously:
type DefaultCellComponentProps<TCellData = any, TField extends ClientField = ClientField>
New:
type DefaultCellComponentProps<TField extends ClientField = ClientField, TCellData = undefined>
You can override the cellData type by passing in the second argument to the generic. ie if you know the shape of your data differs than the inferred type then you can do something like:
DefaultCellComponentProps<RelationshipFieldClient, { myShape: string, here: string }>
storage-uploadthing: upgrade to v7 (#8346) (4690cd8)
Upgrade uploadthing to v7
The options
that can be passed to the plugin now mirror the
UTApiOptions
of v7.
The most notable change is to pass token
with
process.env.UPLOADTHING_TOKEN
instead of apiKey
with
process.env.UPLOADTHING_SECRET
.
options: {
- apiKey: process.env.UPLOADTHING_SECRET,
+ token: process.env.UPLOADTHING_TOKEN,
acl: 'public-read',
},
state
when creating first user (#9168) (3b55458)This is a significant release which overhauls the way that we render, and provide, custom React components to the Payload Admin UI. Now, custom server components receive contextual props, like data
and value
, so you can do considerably more with them on the server.
It also ships with a variety of performance improvements to the server-side rendering done for the admin panel.
There are a few relatively simple breaking changes outlined below.
useAsTitle
to the popup links label (#8718) (23907e4)user
for document locking (#9139) (48d0fae)relationTo
to locked documents creation (#9137) (3298113)on-demand rsc (#8364) (c96fa61)
Add the following to your root layout file, typically located at (app)/(payload)/layout.tsx
:
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
+ import type { ServerFunctionClient } from 'payload'
import config from '@payload-config'
- import { RootLayout } from '@payloadcms/next/layouts'
+ import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts'
import React from 'react'
import { importMap } from './admin/importMap.js'
import './custom.scss'
type Args = {
children: React.ReactNode
}
+ const serverFunction: ServerFunctionClient = async function (args) {
+ 'use server'
+ return handleServerFunctions({
+ ...args,
+ config,
+ importMap,
+ })
+ }
const Layout = ({ children }: Args) => (
<RootLayout
config={config}
importMap={importMap}
+ serverFunction={serverFunction}
>
{children}
</RootLayout>
)
export default Layout
If you were previously posting to the /api/form-state
endpoint, it
no longer exists. Instead, you'll need to invoke the form-state
Server
Function, which can be done through the new getFormState
utility:
- import { getFormState } from '@payloadcms/ui'
- const { state } = await getFormState({
- apiRoute: '',
- body: {
- // ...
- },
- serverURL: ''
- })
+ const { getFormState } = useServerFunctions()
+
+ const { state } = await getFormState({
+ // ...
+ })
Multiple layer of React Context were removed in favor of direct props. As a result, the following React hooks were removed:
- useFieldProps()
- useTableCell()
If you were previously using any of these hooks, for example to access field path
or cellData
, you can now access that directly from the props
object.
- const { path } = useFieldProps();
+ const { path } = props;
- const { cellData } = useTableCell();
+ const { cellData } = props;
The field
prop also no longer contains a _schemaPath
property. Instead, this is now also accessed directly through props:
- const { _schemaPath } = props.field
+ const { schemaPath } = props
db-mongodb: use dbName for mongodb model (#9107) (09c41d5)
If a dbName
was previously provided, it will now be used as the
MongoDB collection name instead of the collection slug
.
autoPluralization
will not be applied to dbName
.
richtext-lexical: upgrade lexical from 0.18.0 to 0.20.0 (#9126) (7767c94)
This upgrades our lexical dependencies from 0.18.0 to 0.20.0. If you have lexical dependencies installed in your project, you will have to upgrade those.
Additionally, the lexical team may introduce breaking changes in this upgrade. If you use lexical APIs directly, please consult their changelog for more information: https://github.com/facebook/lexical/releases
populate
with find operation (#9087) (721ae79)totalDocs
with joins (#9056) (f67761f)handle custom id logic in mongodb adapter (#9069) (ee117bb)
When using custom ID fields, if you have any collection hooks for
beforeValidate, beforeChange then data._id
will no longer be assigned
as this happens now in the database adapter. Use data.id
instead.
joins
(#9054) (213b7c6)populate
property to Local / REST API (#8969) (a22c0e6)createDatabase
(#9022) (147d28e)PointerEvents
to show tooltips on enabled / disabled buttons (#9006) (d425290)where
property (#8973) (93a55d1)method: 'put'
(#9037) (9ce2ba6)RequestContext
(#9035) (f52b7c4)updatedAt
field in locked-docs collection able to be updated by non-owner (#9026) (ebd3c02)select
type with strictNullChecks: true
(#8991) (4349b78)id
path with REST (#9013) (5b97ac1)select
with unnamed tabs (#8966) (3175541)read
access for users
(#8950) (55ce8e6)findByID
with strict: true
(#8953) (08251ec)ReactSelect
(#8735) (c0397c3)