v3.60.0
Version v3.60.0Minor Release
Release Notes
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'],},]ts
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 differentif (accessKey === 'read') {return {or: [{isShared: {equals: true,}},accessResult]}} else {return accessResult}}}}})ts - 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 pluginreturn accessResult}ts
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. #13813 <https://github.com/user-attachments/assets/cfc0d2a8-ffb3-4926-b097-ad9c2b133586>
๐ 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)
๐ Refactors
๐ Documentation
- revert sentry docs change (#14113) (8844eaf)
- incorrect pg driver injection example in Sentry integration docs (#14088) (95dbaed)
๐งช Tests
โ๏ธ CI
- notify website repo on release [skip ci] (#14140) (a36e5d2)
- add website dispatch event, testing for releases [skip ci] (#14138) (b0d31ba)
- add missing labels to bug report template [skip ci] (#14134) (3069e5b)
- update generate-template-variations script to cover cloudflare template (#14105) (e78057b)
๐ก Chores
- better audit dependencies script (#14189) (f9e75a4)
- ignore agent local files [skip ci] (#14184) (7ecb5a0)
- drizzle: bump drizzle-orm and drizzle-kit for vulnerabilities (#14200) (4afa286)
- email-nodemailer: bump nodemailer dependencies to latest (#14121) (077c6f5)
๐ค Contributors
- Sasha (@r1tsuu)
- Patrik (@PatrikKozak)
- Paul (@paulpopus)
- Jessica Rynkar (@jessrynkar)
- German Jablonski (@GermanJablo)
- Elliot DeNolf (@denolfe)
- Elliott W (@elliott-w)
- Jarrod Flesch (@JarrodMFlesch)
- Alessio Gravili (@AlessioGr)
- Diogo Gaspar (@shadowoff09)