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)