Releases: payloadcms/payload
v3.64.0
v3.64.0 (2025-11-13)
🚀 Features
- add support for UTC timezone in date fields (#14586) (8b34e40)
- next: turbopack build support, fix incorrect handling of external packages (#14475) (3a975d7)
- plugin-mcp: adds MCP context to req.payloadAPI (#14595) (860bdf2)
- plugin-mcp: adds custom auth config (#14538) (73a18dc)
- plugin-redirects: support translations (#14548) (ad8f0b2)
UTC Timezone Support - Add support for 'UTC' as a timezone value in date fields. Previously unsupported due to validation against Intl API runtime values. Also fixes issue where having only one timezone would make it selected by default. #14586
import { buildConfig } from 'payload' const config = buildConfig({ admin: { timezones: { supportedTimezones: [ { label: 'UTC', value: 'UTC', }, ], defaultTimezone: 'UTC', }, }, })Turbopack Build Support - Full support for Turbopack builds (now default in Next.js 16). Properly externalizes database adapter entry points to prevent production failures. Resolves issues with direct dependency externalization causing runtime errors. #14475
MCP Context Detection - Detect when Payload API calls originate from MCP context using req.payloadAPI === 'MCP'. Enables conditional logic in hooks based on MCP usage. #14595
export const Posts: CollectionConfig = { slug: 'posts', hooks: { beforeRead: [ ({ doc, req }) => { if (req.payloadAPI === 'MCP') { doc.title = `${doc.title} (MCP Hook Override)` } return doc }, ], }, }Custom Auth Configuration - Override default API key authentication with custom authorization logic using overrideAuth. Provides granular control over MCP access permissions. #14538
import { type MCPAccessSettings, mcpPlugin } from '@payloadcms/plugin-mcp' plugins: [ mcpPlugin({ overrideAuth: (req) => { return { posts: { find: true }, products: { find: true, update: true }, } as MCPAccessSettings }, }) ]Redirect Plugin Translation Support - Enable translations for plugin fields, eliminating need for verbose field overrides configuration. Configure field labels in multiple languages directly through i18n config. #14548
export default buildConfig({ i18n: { translations: { en: { 'plugin-redirects': { fromUrl: 'Source URL (Custom)', }, }, de: { 'plugin-redirects': { fromUrl: 'Quell-URL', internalLink: 'Interner Link', }, }, }, }, plugins: [redirectsPlugin({ collections: ['pages'] })], })🐛 Bug Fixes
- previous value undefined for nested fields in afterChange (#14582) (d60ea6e)
- default values inconsistent between Local and REST APIs (#14556) (8f7ef35)
- findGlobalVersionByID id type (#14534) (99ed0e5)
- localized block fields (#14587) (2295c89)
- add secondary PDF mimeType validation and tests (#14529) (ce479ab)
- unlock access not being correctly denied when using a where query (#14585) (f63e34e)
- error when calling jobs.handleSchedules when there are no schedules defined (#14519) (072cb97)
- changing the language of the admin panel does not work for "radio" and "select" fields. (#14569) (bb520d6)
- inject custom translations into supportedLanguages in sanitization (#14549) (d7f1ea2)
- db-mongodb: localization transforms on nested localized fields (#14600) (6070d8d)
- db-mongodb: findVersions/findGlobalVersions not respecting limit of 0 (#14573) (43dcf84)
- graphql: avoid errors with sort as empty string (#14594) (fad476d)
- next: turbopack error when using db-d1-sqlite package (#14558) (bd6decf)
- next, ui: show status "changed" in List View (#14555) (565680d)
- plugin-form-builder: expose formSubmissionID as a variable to be used in emails (#14429) (ad74386)
- plugin-mcp: correctly uses local access controls (#14457) (fc2becf)
- richtext-lexical: urls being wrongly encoded by incomplete URL validation (#14557) (2cb0c59)
- storage-r2: respect data.prefix in handleUpload path construction (#14485) (454d0d3)
- ui: error on inserting new documents on uploads with hasMany (#14567) (fd44d2b)
- ui: save button becomes disabled after failed save with draft validation (#14584) (6fda71a)
- ui: invalid req.locale shows incorrect data (#14537) (f29a07f)
⚡ Performance
🛠 Refactors
📚 Documentation
🧪 Tests
- move draft validation tests from form-state to field error states test suite (#14599) (e1f07ff)
- run cpa against create-next-app latest and canary (#14583) (cca97c6)
- 21x faster versions int suite (#14510) (844f99f)
📝 Templates
⚙️ CI
🏡 Chores
- add .worktrees to .gitignore (87f2bd9)
- fix serverExternalPackages errors in monorepo (#14535) (e76da3f)
🤝 Contributors
- Kendell (@kendelljoseph)
- Jarrod Flesch (@JarrodMFlesch)
- Patrik (@PatrikKozak)
- Paul (@paulpopus)
- German Jablonski (@GermanJablo)
- Jessica Rynkar (@jessrynkar)
- Sasha (@r1tsuu)
- Sam (@damnsamn)
- Alessio Gravili (@AlessioGr)
- Tobias Odendahl (@tak-amboss)
- Elliot DeNolf (@denolfe)
- Jens Becker (@jhb-dev)
- Sean Zubrickas (@zubricks)
v3.63.0
v3.63.0 (2025-11-07)
🚀 Features
- add support for polymorphic uploads (#14363) (df40d0e)
- adds new UI option Duplicate In [Select Locales] (#13803) (53d8557)
Polymorphic Uploads
Upload fields can now reference multiple upload collections, similar to polymorphic relationships. This enables more flexible media management where a single field can accept different types of files from various collections. Works seamlessly with bulk upload and hasMany options. #14363
import type { CollectionConfig } from 'payload' export const ExampleCollection: CollectionConfig = { slug: 'example-collection', fields: [ { name: 'media', type: 'upload', relationTo: ['images', 'documents', 'videos'], // references multiple upload collections }, ], }Can also be combined with hasMany:
import type { CollectionConfig } from 'payload' export const ExampleCollection: CollectionConfig = { slug: 'example-collection', fields: [ { name: 'media', type: 'upload', relationTo: ['images', 'documents', 'videos'], // references multiple upload collections hasMany: true, // allows multiple uploads }, ], }🐛 Bug Fixes
- use
TSiblingDataforpreviousSiblingDocinFieldHook(#14503) (339a0c3) - support generic types for kv.get (#14494) (f6194c6)
- group-by sticky pagination not rendering for virtual relationship fields (#14470) (648021c)
- ensure importMap is reliably generated during HMR (fixes Next.js 16 issue) (#14474) (61a7095)
- hmr not working in next.js 16 (#14462) (0231a8d)
- disable
lockedDocumentsif the kv adapter uses a collection (#14453) (827c9a1) - drizzle: postgesql where in jsonb (#13742) (207295b)
- graphql: sort by multiple fields (#14486) (b925d34)
- next: withPayload wrapper next.js 16 support (#14473) (c0de75e)
- next: version._status field queried/returned for entities without drafts (#14423) (a22dff3)
- plugin-cloud-storage: file sizes use correct mime type (#11633) (2410296)
- richtext-lexical: prevent unnecessary requests for inline blocks (#14522) (69408f0)
- richtext-lexical: bulk upload drawer rendered at the wrong depth if already in a drawer (#14472) (4fd8d03)
- ui: virtual fields disappearing from filter/groupBy dropdowns with access control (#14514) (a3c0e84)
- ui: safely access fieldPermissions (#14458) (2393721)
- ui: simplify UI orderable collections table by allowing only ascending order (#14433) (eba6cfc)
⚡ Performance
🛠 Refactors
📚 Documentation
🧪 Tests
- use new chromium headless browser for playwright, bump playwright (#14464) (2bb5535)
- multi-tenant flake (#14447) (80d7781)
📝 Templates
- remove payload cloud template, remove cloud plugin from templates (#14479) (76ba2df)
- remove outdated cloning and payload cloud information (#14484) (d4d9622)
🔨 Build
⚙️ CI
- speed up workflow reruns, remove run_number from build cache key (#14448) (f67d031)
- add kv and plugin-mcp to valid PR scopes (be0943a)
🏡 Chores
- standardize query param parsing (#14498) (3c9f56e)
- enables folders on website template (#14116) (219fba2)
- bump kv-redis version (ff670c0)
- claude: update claude PostToolUse hook to only format on write (9f2adeb)
- claude: set some sane defaults (#14445) (aa14d86)
- claude: add analyze-issue command (#14435) (f1456a0)
🤝 Contributors
- Sasha (@r1tsuu)
- Elliot DeNolf (@denolfe)
- Chris Rieckmann (@c-riq)
- Sam Wheeler (@swheeler7)
- Alessio Gravili (@AlessioGr)
- Slava Nossar (@slavanossar)
- Jacob Fletcher (@jacobsfletch)
- Patrik (@PatrikKozak)
- Paul (@paulpopus)
- Tobias Odendahl (@tak-amboss)
- Kendell (@kendelljoseph)
- Jessica Rynkar (@jessrynkar)
- German Jablonski (@GermanJablo)
- Sean Zubrickas (@zubricks)
- Violet Rosenzweig (@6TELOIV)
v3.62.1
v3.62.0
v3.62.0 (2025-10-30)
🚀 Features
Jobs Access Control
Adds role-based access control for job queue and cancel operations, allowing you to restrict who can manage background jobs in your application. Both operations now support overrideAccess parameter and respect custom access control functions defined in your jobs configuration. #14404
// Configure access control jobs: { access: { queue: ({ req }) => req.user?.roles?.includes('admin'), cancel: ({ req }) => req.user?.roles?.includes('admin'), } } // Use in Local API await payload.jobs.cancel({ where: { workflowSlug: { equals: 'sync' } }, overrideAccess: false, req, })Per-Field Timezone Configuration
Date fields can now have individual timezone settings, allowing different date fields to support their own list of supported timezones with custom default values. This enables more flexible date handling across your application. #14410
{ name: 'date', type: 'date', timezone: { defaultTimezone: 'America/New_York', supportedTimezones: [ { label: 'New York', value: 'America/New_York' }, { label: 'Los Angeles', value: 'America/Los_Angeles' }, { label: 'London', value: 'Europe/London' }, ], }, }You can also enforce a specific timezone by specifying just one with a default value:
{ name: 'date', type: 'date', timezone: { defaultTimezone: 'Europe/London', supportedTimezones: [ { label: 'London', value: 'Europe/London' }, ], }, }KV Storage Adapters
Introduces a new key-value storage system with multiple adapter options (Database, In-Memory, Redis) for enhanced data persistence and performance. This provides the foundation for the upcoming Realtime API and other features requiring fast key-value access. #9913
Access the KV store via payload.kv with the following interface:
interface KVAdapter { /** * Clears all entries in the store. * @returns A promise that resolves once the store is cleared. */ clear(): Promise<void> /** * Deletes a value from the store by its key. * @param key - The key to delete. * @returns A promise that resolves once the key is deleted. */ delete(key: string): Promise<void> /** * Retrieves a value from the store by its key. * @param key - The key to look up. * @returns A promise that resolves to the value, or `null` if not found. */ get(key: string): Promise<KVStoreValue | null> /** * Checks if a key exists in the store. * @param key - The key to check. * @returns A promise that resolves to `true` if the key exists, otherwise `false`. */ has(key: string): Promise<boolean> /** * Retrieves all the keys in the store. * @returns A promise that resolves to an array of keys. */ keys(): Promise<string[]> /** * Sets a value in the store with the given key. * @param key - The key to associate with the value. * @param value - The value to store. * @returns A promise that resolves once the value is stored. */ set(key: string, value: KVStoreValue): Promise<void> }Configure the adapter using the kv property:
buildConfig({ kv: adapter() })Database KV adapter (default) - Uses your existing database with a hidden payload-kv collection:
import { databaseKVAdapter } from 'payload' buildConfig({ kv: databaseKVAdapter({ kvCollectionOverrides: { slug: 'custom-kv', ...(process.env.DEBUG === 'true' && { admin: { hidden: false }, access: {}, }), }, }), })In Memory KV adapter - Fast memory-based storage for development:
import { inMemoryKVAdapter } from 'payload' buildConfig({ kv: inMemoryKVAdapter(), })Redis KV Adapter - Production-ready Redis integration:
pnpm add @payloadcms/kv-redisimport { redisKVAdapter } from '@payloadcms/kv-redis' buildConfig({ kv: redisKVAdapter({ keyPrefix: "custom-prefix:", // defaults to 'payload-kv:' redisURL: "redis://127.0.0.1:6379" // defaults to process.env.REDIS_URL }), })Configurable Toast Position
Toast notifications can now be positioned anywhere on the screen (top-left, top-center, top-right, bottom-left, bottom-center, bottom-right), giving you control over where important messages appear to your users. This is particularly useful for applications with large screens or specific UI layouts. #14405
The position configuration is a direct pass-through of the Sonner library's position options, with 'bottom-right' remaining the default.
Feature PRs
- add access control for jobs queue and cancel operations (#14404) (0a37edb)
- timezone config can now be added on a per field basis (#14410) (a3df837)
- add KV storage adapters (#9913) (ffb9a2e)
- make toast position configurable (#14405) (d5fab43)
- ui: export useQueue React hook (#14396) (612880d)
🐛 Bug Fixes
- globals with versions return _status field when access denied (#14406) (b766ae6)
- custom dashboard component causes runtime error on create-first-user and account views (#14393) (d5f4e72)
- claude: remove invalid frontmatter fields (#14411) (118d005)
- db-*:
findMigrationDirin projects withoutsrcfolder (#14381) (059185f) - db-mongodb: migration fails for cosmosDB (#14401) (10a640c)
- db-mongodb: type error with
prodMigrations(#14394) (8e5e23a) - db-mongodb: duplicate ids in sanitizeQueryValue (#11905) (36bb188)
- db-postgres: hasMany relationship/number/text fields inside blocks are incorrectly returned when using
select(#14399) (850cc38) - drizzle: number fields in generated schema with
defaultValue(#14365) (8996b35) - plugin-multi-tenant: remove unused syncTenants from useEffect deps (#14362) (906a3dc)
- richtext-lexical: do not run json.parse if value is undefined or null (#14385) (09a6140)
- richtext-lexical: prevent TS CodeBlocks from sharing Monaco model (useId) (#14351) (5caebd1)
- storage-*: update the client cache to use a map instead with cache keys per bucket config (#14267) (38f2e1f)
- ui: where builder crashing with invalid queries (#14342) (6c83046)
🛠 Refactors
- deprecate job queue depth property (#14402) (1341f69)
- ui: simplify ConfigProvider, improve useControllableState types and defaultValue fallback (#14409) (255320e)
⚙️ CI
- add claude as valid scope (560f2f3)
🤝 Contributors
- Dan Ribbens (@DanRibbens)
- Alessio Gravili (@AlessioGr)
- Paul (@paulpopus)
- Elliot DeNolf (@denolfe)
- Sasha (@r1tsuu)
- Patrik (@PatrikKozak)
- Ossaid Qadri (@imossaidqadri)
- Philipp Schneider (@philipp-tailor)
- Kholiavko Roman (@kholiavko-roman)
- Jacob Fletcher (@jacobsfletch)
- Séalan Cronin (@sealan)
- Jarrod Flesch (@JarrodMFlesch)
- Justus Blönnigen (@technicaldirector)
v3.61.1
v3.61.1 (2025-10-24)
🐛 Bug Fixes
- ui: ask before closing doc drawer with edits (#14324) (c1d017a)
- filteredLocales in the client config are stale (#14326) (5a37909)
- db-*: querying joins with
$existson mongodb and improve performance when querying multiple times on postgres (#14315) (1f166ba) - db-postgres: regression in migrations in the
_relstable (#14341) (a2b1c9b) - plugin-search: add locale to key in syncedDocsSet (#14289) (c29e1f0)
- ui: account for array values in transformWhereToNaturalLanguage (#14339) (f2cabe7)
- ui: preview button not responding to conditional URL (#14277) (ad0e7b2)
- ui: use
depth: 0for publish specific locale request (#14313) (b68715e)
📚 Documentation
- various grammar and typo fixes (#14170) (c96d50d)
- adds example for name or label on groups field (#14323) (6d88f7d)
🤝 Contributors
- Jarrod Flesch (@JarrodMFlesch)
- Boyan Bratvanov (@bratvanov)
- Sasha (@r1tsuu)
- Sean Zubrickas (@zubricks)
- Said Akhrarov (@akhrarovsaid)
- Paul (@paulpopus)
v3.61.0
v3.61.0 (2025-10-23)
🚀 Features
- @payloadcms/plugin-mcp Released (BETA) - New plugin that enables Payload to function as an MCP server, allowing AI models to interact with your collections through a standardized protocol. The plugin provides built-in tools for CRUD operations on collections and supports custom tools. #13674
🐛 Bug Fixes
- user updatedAt modified during session operations (#14269) (a1671ec)
- document header text clipping (#14291) (db973e9)
- typescript requires fields when draft: true despite passing
draft: true(#14271) (1016cd0) - blocks access control not respecting update access whether on collection or on a per field basis (#14226) (88cb687)
- allow slugField to accept localized argument and fixed slug generation with custom field names (#14234) (2ced43d)
- db-postgres: limit index and foreign key names length (#14236) (a63b4d9)
- drizzle: folders with trash enabled don't display documents in polymorphic joins (#14223) (6d3aaaf)
- plugin-form-builder: display full textarea content in form submissions (#14161) (24dad01)
- plugin-multi-tenant: block references issue (#14320) (4f8b7d2)
- plugin-search: exclude skipped drafts in reindex handler (#14224) (0dc782c)
- richtext-lexical: ensure block node form displays up-to-date value when editor remounts (#14295) (f8e6b65)
- richtext-lexical: node replacements ignored for block, inline block, upload, unknown and relationship nodes (#14249) (1561853)
- richtext-lexical, ui: ui errors with Slash Menu in Lexical and SearchBar component in RTL (#14231) (fed3bba)
- ui: document locked modal blocks interaction after clicking Go Back (#14287) (5782a41)
- ui: change password button being hidden and unlock button being shown incorrectly on account page (#14220) (bcb4d8e)
⚡ Performance
- richtext-lexical: decrease size of field schema, minor perf optimizations (#14248) (e25ce1c)
- richtext-lexical: do not return i18n from editor adapter (#14228) (54224c3)
🛠 Refactors
📚 Documentation
- improve slate to lexical migration docs (#14309) (6838c56)
- db indexes - code example missing const (#14171) (3b37f4a)
- add explanation about re-renders in
useFormFields(#14288) (8cdb5dc) - add jsdocs to RichText adapter (#14246) (8b0ac01)
- clarify
admin.timezoneslist configuration with example (#14238) (de5f3db) - fix link to slug-overrides in text.mdx (#14211) (8136a84)
- add mention of the useUploadHandlers error and steps to remedy it with a mention to monorepos (#14233) (8663024)
🔨 Build
- add plugin-mcp to publishList (#14319) (894cf0c)
- add README sync for top-level -> packages/payload (#14316) (2aba827)
🏡 Chores
- extract snapshot logic, correct types in version ops (#14290) (c2dcd12)
- bump pino to v9.14.0 and pino-pretty (#14283) (b252658)
- refresh CLAUDE.md (#14268) (05a869d)
- cleanup, short-circuit .split calls (#14245) (d57be12)
🤝 Contributors
- Jarrod Flesch (@JarrodMFlesch)
- Elliot DeNolf (@denolfe)
- Kendell (@kendelljoseph)
- Alessio Gravili (@AlessioGr)
- Patrik (@PatrikKozak)
- Boyan Bratvanov (@bratvanov)
- Paul (@paulpopus)
- German Jablonski (@GermanJablo)
- Bogdan Covrig (@bogdaaamn)
- Romain Pironneau (@romainpi)
- Sasha (@r1tsuu)
- Ahmed Abdellahi Abdat (@ahmed-abdat)
- Said Akhrarov (@akhrarovsaid)
v3.60.0
v3.60.0 (2025-10-16)
🚀 Features
- accept multiple locales in fallbackLocale (#13822) (623a1b8)
- adds settingsMenu to admin navigation sidebar (#14139) (ee8b3cf)
- plugin-multi-tenant: allow collection access to be overridden via callback (#14127) (c40eec2)
- plugin-multi-tenant: allow hasMany on tenant field overrides (#14120) (fb93cd1)
- plugin-multi-tenant: user collection access overrides (#14119) (38b7a60)
- richtext-lexical: add collection filtering to UploadFeature, refactor relationship hooks (#14111) (6defba9)
- richtext-lexical: client-side block markdown shortcuts, code block (#13813) (07a1eff)
Localization
-
Multiple fallback locales -
fallbackLocalenow accepts an array of locales for queries and locale configs. Payload will check each locale in order until finding a value, eliminating the need for manual fallback handling. #13822/** Local API **/ await payload.findByID({ id, collection, locale: 'en', fallbackLocale: ['fr', 'es'], }) /** REST API **/ await fetch(`${baseURL}/api/${collectionSlug}?locale=en&fallbackLocale[]=fr&fallbackLocale[]=es`) /** GraphQL **/ await restClient.GRAPHQL_POST({ body, query: { locale: 'en', fallbackLocale: ['fr', 'es']}, }) /** Locale Configs **/ locales: [ { code: 'en', label: 'English', fallbackLocale: ['fr', 'es'], }, ]
Admin UI
-
Settings menu in navigation - New
admin.components.settingsMenuconfig option adds a gear icon above the logout button. Click to open a popup menu with custom admin-level utilities and actions that don't fit into collection or global navigation. #14139
Multi-Tenant Plugin
-
Collection access overrides - New
accessResultOverridecallback allows modifying multi-tenant access control results per operation (read, create, update, delete, readVersions, unlock). Enables custom logic like allowing shared content across tenants. #14127multiTenantPlugin<ConfigType>({ collections: { posts: { accessResultOverride: async ({ accessResult, accessKey, req }) => { // here is where you can change the access result or return something entirely different if (accessKey === 'read') { return { or: [ { isShared: { equals: true, } }, accessResult ] } } else { return accessResult } } } } })
-
Multiple tenants per document - Tenant field overrides now support
hasManyrelationships, allowing documents to belong to multiple tenants. #14120 -
User collection access overrides - New
usersAccessResultOverridecallback enables customizing access control on the users collection, overriding default tenant privacy when needed. #14119usersAccessResultOverride: ({ accessKey: 'read', // 'create', 'read', 'update', 'delete', 'readVersions', 'unlock' accessResult: AccessResult, // the `AccessResult` type ...args, // AccessArgs }) => { // this is where you could adjust what gets returned here. if (accessKey === 'read') { return true // over simplified example } // default to returning the result from the plugin return accessResult }
Lexical Rich Text
-
Upload collection filtering -
UploadFeaturenow supportsdisabledCollectionsandenabledCollectionsto control which collections appear in the upload drawer. Also refactors enabled relationships logic with cleaneruseEnabledRelationshipshook. #14111 -
Client-side markdown shortcuts & code blocks - Blocks with
admin.jsxnow support markdown shortcuts on the client (previously server-only). Includes pre-madeCodeBlockcomponent for use inBlocksFeature. Also fixesreadOnlyhandling across nested fields. #13813Screenshot.2025-10-01.at.10.14.54.mp4
🐛 Bug Fixes
findDistinctby explicit ID paths in relationships and virtual fields (#14215) (2b1b6ee)- hasMany / polymorphic relationships to custom number IDs (#14201) (a3b3865)
- hide fields with read: false in list view columns, filters, and groupBy (#14118) (bcd40b6)
- validate Point Field to -180 to 180 for longitude and -90 to 90 for latitude (#14206) (13a1d90)
- urls in upload sizes are not encoded (#14205) (747a049)
- restoring trashed drafts with empty required fields fails validation (#14186) (3317207)
- db-d1-sqlite: add missing
blocksAsJSONproperty (#14103) (f14a38e) - db-mongodb: documents not showing in folders with
useJoinAggregations: false(#14155) (e613a78) - db-mongodb: improve check for
ObjectId(#14131) (32e2be1) - graphql: bump tsx version to get around esbuild vulnerability (#14207) (d7ec48f)
- next: custom views not overriding built-in single-segment routes (#14066) (691f810)
- plugin-multi-tenant: object reference mutations in addFilterOptionsToFields (#14150) (e62f1fe)
- richtext-lexical: state key collisions when multiple TextStateFeatures are registered (#14194) (f01a6ed)
- richtext-lexical: editor throws an error if OrderedList is registered but not UnorderedList or CheckList (#14149) (1fe75e0)
- richtext-lexical: editing a copied inline block also modifies the original (#14137) (5bacb38)
- richtext-lexical: correctly type field property of RenderLexical (#14141) (cd94f8e)
- richtext-lexical: improve type autocomplete and assignability for lexical nodes (#14112) (a46faf1)
- sdk:
paginationis not passed to search params (#14126) (ee9f160) - storage-gcs: bump @google-cloud/storage for vulnerability (#14199) (1077aa7)
- storage-r2: uploads with prefix don't work, add
test/storage-r2(#14132) (4fd4cb0) - templates: encoding and decoding slugs in website template (#14216) (cacf523)
- templates: ecommerce seeding issue (#14196) (d65b8c6)
#...
v3.59.1
v3.59.1 (2025-10-07)
🐛 Bug Fixes
- revert drizzle-orm (#14108) (ee78eb2)
- plugin-multi-tenant: not setting cookie properly on login (#14107) (5590535)
- ui: update memory user when autoLogin enabled (#14018) (c2fa629)
⚙️ CI
- update activity notification channels (72be9d3)
🏡 Chores
- update lock (7e12880)
🤝 Contributors
- Jarrod Flesch (@JarrodMFlesch)
- Elliot DeNolf (@denolfe)
v3.59.0
v3.59.0 (2025-10-07)
🚀 Features
- slug field (#14007) (b09ae67)
- support any depth for relationships in
findDistinct(#14090) (e4f8478) - adds
disableGroupByto fields admin props (#14017) (537f58b) - allow
findDistincton fields nested to relationships and on virtual fields (#14026) (9d6cae0) - bundle types (#14020) (9bcb7b0)
- cpa: add cloudflare template to create-payload-app command (#14091) (e8140ed)
- db-*: adds support for readReplicas in D1 adapter config (#14040) (5a6f361)
- db-mongodb,drizzle: add atomic array operations for relationship fields (#13891) (7eacd39)
- next: export views, pass all props to custom dashboard view (#14094) (abebd24)
- plugin-nested-docs: pass collection config as an arg to generateURL and generateLabel (#14086) (db6ec30)
- ui: add support for disabling join field row types (#12738) (cd546b3)
- ui: live preview conditions (#14012) (2be6bb3)
🐛 Bug Fixes
- add detection for --experimental-https flag (#14085) (3cf3f93)
- missing cross-env in deploy:database (#14076) (709ee58)
- support USE_HTTPS for local hmr (#14053) (feaa395)
- update packages list for
pnpm payload info(#14030) (4b6b0c5) autosave: truedoesn't work onpayload.updatewithwhere(#14001) (5d86d5c)- db-d1-sqlite: avoid bound parameter limit when querying relationships and inserting rows (#14099) (444ca0f)
- db-mongodb: localized blocks with fallback and versions (#13974) (1e654c0)
- db-postgres:
drizzledoesn't recognize types from the generated types (#14058) (ef84b20) - db-postgres: querying multiple hasMany text or number fields (#14028) (95bdffd)
- db-postgres: joins count with hasMany relationships (#14008) (1510e12)
- drizzle: generate DB schema syntax is deprecated (#14031) (ef57d24)
- graphql: error querying hasMany relationships when some document was deleted (#14002) (48e9576)
- next: force inactive live preview after passing conditions (#14048) (ca3f054)
- next: prevent locale upsert when not authenticated (#13621) (ece5a95)
- plugin-ecommerce: variants
validateOptionserrors with SQLite when creating a new variant (#14054) (3b9e759) - plugin-multi-tenant: rm chalk dep (#14003) (d017499)
- plugin-search: handle trashed documents in search plugin sync (#13836) (de352a6)
- richtext-lexical: field.admin overrides were ignored in RenderLexical helper (#14024) (810da54)
- richtext-lexical: slash menu arrows keys not respected when block nearby (#14015) (54b6f15)
- sdk: incorrect
fetchinitialization on cloudflare (#14009) (a5c8b5b) - storage-r2: upload with the correct contentType (#13988) (066997d)
- storage-uploadthing: hide key field from filters and columns (#14004) (2ce6e13)
- templates: ignore wrangler when bundling to fix template styles (#14067) (c135bf0)
- templates: added missing CLOUDFLARE_ENV in cloudflare template when optimizing database (#14064) (9fcd1fa)
- templates: don't use remote bindings in cloudflare template when developing locally (#14063) (9d3e540)
- templates: ecommerce wrong links in readme and docs and issue with missing graphql dependency (#14045) (e4f90a2)
- templates: correct typo in footer text (#14021) (a938ad6)
- translations: refine Persian (fa) translations for clarity and natural tone (#14082) (990603c)
- translations: fixes to Icelandic translations (#14038) (7088d25)
- translations: fixes to Swedish translation (#13994) (4b193da)
- ui: phantom fields when duplicating rows with rows (#14068) (08f6d99)
- ui: invalid time value error when document locking with autosave enabled (#14062) (394000d)
- ui: undefined access with polymorphic joins and fix joins test config (#14057) (cb7a24a)
- ui: popup list controls overlap with table in list view (#13967) (1e23882)
- ui: upload dropzone error when collectionConfig is undefined (#14043) (62fcf18)
- ui: saving empty code editor throw error (#14019) (bffb9ef)
- ui: add support back for custom live preview components (#14037) (d826159)
- ui: array fields not respecting width styles in row layouts (#13986) (accd95e)
⚡ Performance
v3.58.0
v3.58.0 (2025-09-30)
🚀 Features
Ecommerce plugin and template (#8297) (ef4874b)
The Ecommerce Template and Plugin is now ready in beta, you can get started by running the Payload CPA command below
pnpx create-payload-app my-project -t ecommerce Full docs are available on our website
Payload SDK package (#9463) (92a5f07)
Allows querying Payload REST API in a fully type safe way. Has support for all necessary operations, including auth, type safe select, populate, joins properties and simplified file uploading. Its interface is very similar to the Local API.
import { PayloadSDK } from '@payloadcms/sdk' import type { Config } from './payload-types' // Pass your config from generated types as generic const sdk = new PayloadSDK<Config>({ baseURL: 'https://example.com/api', }) // Find operation const posts = await sdk.find({ collection: 'posts', draft: true, limit: 10, locale: 'en', page: 1, where: { _status: { equals: 'published' } }, })New Cloudflare D1 SQLite adapter, R2 storage adapter and Cloudflare template (#12537) (99043ee)
You can now deploy directly to Cloudflare using our 1-click template or click the deployment button below
🐛 Bug Fixes
- ensure blocks filterOptions are awaited (#13960) (41aa201)
- sanitize collection labels to inherit defaults when only a partial config is provided (#13944) (1752043)
- avoid relying on
Function.prototype.nameto detect react components (#13931) (4652bd0) - next: static live preview url corrupt after save (#13949) (3c4f8a3)
- plugin-multi-tenant: properly localize labels (#13943) (2cc34d1)
- richtext-lexical: editor re-mounting on save due to json key order not being preserved in postgres (#13962) (6a2e814)
- ui: query preset where field not displaying array values (#13961) (9248fc4)
- ui: move collection description below title in document view (#13946) (ae34b6d)
⚙️ CI
- add
@payloadcms/sdkto publish list (#13964) (f9743b4) - add cron to activity notifications [skip ci] (#13959) (6d995ff)
- proper path for activity notifications [skip ci] (2514e4d)
- activity-notifications debug inputs (ba33f2f)
- github activity slack notifications (#13955) (4562df7)
🏡 Chores
- update templates and docs links (#13971) (d7888df)
- rename activity notifications workflow (f7b1b7b)
- sdk: add README (#13975) (2e1fb57)
🤝 Contributors
- Elliot DeNolf (@denolfe)
- Sasha (@r1tsuu)
- Paul (@paulpopus)
- Patrik (@PatrikKozak)
- Alessio Gravili (@AlessioGr)
- Jacob Fletcher (@jacobsfletch)
- Jarrod Flesch (@JarrodMFlesch)
- Luke Sandberg (@lukesandberg)