Skip to content

Releases: payloadcms/payload

v3.80.0

20 Mar 18:09
e90fb96

Choose a tag to compare

v3.80.0 (2026-03-20)

🚀 Features

  • add disableUnique property to the slug field for better multi tenant plugin support (#15963) (395e1ed)

🐛 Bug Fixes

  • unpublish updates existing version instead of creating a new one (#15985) (67063ab)
  • use latest draft version data when trashing unpublished documents (#15981) (57a0edc)
  • db-mongodb: fix pagination with collation in transactions (#15990) (5c935aa)
  • db-postgres: near query can give incorrect results (#15907) (843306c)
  • db-sqlite: scheduled publish does not show upcoming events because of wrong nested json querying (#15911) (3fa834a)
  • deps: resolve high severity audit vulnerabilities (#15961) (da212fd)
  • drizzle: pagination applied incorrectly when sorting by a field inside an array field (#15908) (0f67215)
  • drizzle: groups inside localized tabs are not working correctly (#15936) (57bde77)
  • graphql: force nullable for relationships to avoid errors when the related document is related (#15915) (560cabe)
  • plugin-mcp: plugin can break next.js request handler because underlying Hono library modifies the global Request object (#15938) (4cfa495)
  • plugin-multi-tenant: modal container blocks clicks on create-first-user page (#15973) (8157f4c)
  • richtext-lexical: richtext fields don't respect RTL direction for Arabic and other RTL locales (#15964) (944a889)
  • ui: defer live preview iframe rendering (#15999) (9999083)
  • ui: stale data modal shown when onChange starts while save is in-flight (#15960) (dc98f0f)

📚 Documentation

📝 Templates

⚙️ CI

🏡 Chores

  • add docker:clean script and fix docker:start reliability (#16000) (2646018)
  • bump monorepo Next.js version to 16.2.0 (#15992) (a188556)
  • consolidate docker scripts into single docker-compose with profiles (#15974) (f89e736)
  • examples: update astro package.json name (#15118) (4e1c04e)

🤝 Contributors

v3.79.1

16 Mar 14:36
25a0e16

Choose a tag to compare

v3.79.1 (2026-03-16)

🐛 Bug Fixes

  • text field validation rejecting localized object values (#15932) (fac59c8)
  • use Sec-Fetch-Site header for cookie authentication validation (#15751) (ef507a6)
  • improved request origin retrieval (#15919) (f30d34f)
  • generate:types inlines all blocks, add forceInlineBlocks property to use in plugin mcp (#15892) (6a9e367)
  • update broken custom components docs link in config types jsdoc (#15794) (17aa1b5)
  • run sanitizeWhereQuery for join query access result (#15891) (dc049fe)
  • early return out of me access (#15883) (c6054c5)
  • scope orderable join reordering by parent relation (#15842) (17a0d19)
  • stricter input validation (#15868) (e474205)
  • drizzle: avoid ts errors for payload generate:db-schema with circular references (#15895) (66a2efa)
  • drizzle: error when using contains operator on hasMany select fields (#15865) (fba2438)
  • drizzle: correctly apply query limit on polymorphic joins (#15652) (fe36dde)
  • plugin-import-export: add space in zh translation for exportDocu… (#15833) (43d5596)
  • plugin-mcp: bump @modelcontextprotocol/sdk from 1.25.2 to 1.27.1 (#15942) (94d2249)
  • storage-azure: add stream aborts for error handling and connection closure (#15768) (b2a03c9)
  • ui: stale data modal incorrectly shown when user saves their own document (#15933) (a5d9388)
  • ui: copy & pasting block content duplicates array items in editor UI (#15941) (9bcedc8)
  • ui: deleted array item reappears after reorder with autosave (#15906) (752c15a)
  • ui: use consistent empty state styling in relationship table (#15914) (93b90da)
  • ui: clicking filtered Combobox entries fails to trigger selection (#15788) (de3e5ae)
  • ui: document status shows changed after publishing specific locale (#15765) (b95df0b)
  • ui: split only on first colon in toast error messages (#15894) (fd64504)
  • ui: block clipboard paste causes duplicate ID errors in Postgres (#15863) (e7d6331)
  • ui: monomorphic relationship fields don't support multi-select with in/not_in operators (#15886) (f71ef61)
  • ui: equal column widths for block-drawer blocks (#15867) (07f7802)
  • ui: isolate join table column preferences from list view (#15846) (649f117)
  • ui: falling back to UTC timezones in timezone picker (#15841) (70099b7)

⚡ Performance

  • richtext-lexical: 3-15x less main thread blocking via centralized toolbar state (#15832) (2bdf7ce)

📚 Documentation

  • correct type name in editMenuItems client component example (#15904) (03b20d0)
  • adds req to available args and wraps examples with proper String type conversions in nested-docs (#15931) (d2a0740)
  • adds docs for logger config (#15927) (46e43fc)
  • fix links to virtual relationship documentation in both Blocks and Array field documentation (#15888) (fff60c8)
  • broken anchor link in blocks field table (#15887) (36c051a)
  • examples: clarify MongoDB prerequisites in Mongo-backed examples (#15860) (2aa973f)
  • plugin-mcp: updates MCP plugin documentation (#15729) (b97b4e7)

🧪 Tests

  • adjust total test count to exclude todo tests in summary output (#15943) (e46daec)
  • fixes pagination and sorting list-view tests due to hydration timing issues (#15925) (b0f00c4)
  • flaky timeout when clicking Create New button in versions test suite (#15850) (3fb10e1)

🏡 Chores

🤝 Contributors

v3.79.0

04 Mar 19:36
6ae6f10

Choose a tag to compare

v3.79.0 (2026-03-04)

🚀 Features

  • richtext-lexical: separate configuration for lexical block icons (#15632) (f0498f2)
  • richtext-lexical: upgrade lexical from 0.35.0 to 0.41.0 (#15760) (ba3bd74)
  • translations: add i18n translations for modular dashboards (#15004) (cef2838)

Separate Block Icon Configuration (richtext-lexical) — Configure different images for Lexical block icons and block drawer thumbnails independently. Previously, imageURL served both contexts, forcing a compromise between a good 20x20px icon and a good drawer thumbnail. The new images property supports separate icon and thumbnail values with automatic fallback. Fully backwards compatible — imageURL still works but is deprecated. #15632

image
const QuoteBlock: Block = {
  slug: 'quote',
  images: {
    icon: 'https://example.com/icons/quote-20x20.svg',
    thumbnail: { url: 'https://example.com/thumbnails/quote-480x320.jpg', alt: 'Quote block' },
  },
  fields: [...],
}

Lexical Upgrade 0.35.0 → 0.41.0 (richtext-lexical) — Upgrades the Lexical rich text editor dependency from v0.35.0 to v0.41.0. Includes upstream fixes like normalizeMarkdown (facebook/lexical#7812). All Lexical breaking changes are handled internally by Payload — no action required for standard usage. If you installed lexical manually, update it to 0.41.0 (though using the re-exported versions from @payloadcms/richtext-lexical/lexical/* is recommended). #15760

Modular Dashboard Translations (translations) — Adds i18n translation support for the Modular Dashboards feature, covering all dashboard widget buttons and error messages. Previously, dashboard UI elements lacked translation keys, making them inaccessible for non-English users. Also updates the automatic translation script to use GPT-4.1 for improved cost efficiency. #15004

image

🐛 Bug Fixes

  • restoreVersion validation for localized required fields (#15821) (e899182)
  • draft doc validation when duplicating docs (#15816) (f470699)
  • plugin-ecommerce: pass req to Payload API calls in Stripe adapter (#15839) (74799ea)
  • plugin-import-export: automatically inherit locale and limit from URL queries (#15812) (ee083f0)
  • plugin-import-export: fix imports with locales in a different column order than exported (#15808) (410912c)
  • plugin-import-export: fix exports in other non-latin scripts being broken when opened in excel (#15813) (d931894)
  • ui: drag and drop not working for sortable hasMany fields (#15845) (2c7ef3f)
  • ui: prevent false positive stale data modal on autosave-enabled documents (#15817) (6aff717)
  • ui: typo in CodeEditor export statement (#15795) (c5b2a91)

🛠 Refactors

  • rename widget ComponentPath to Component for consistency (#15780) (f7d0d04)

📚 Documentation

🧪 Tests

  • update suites selected by default in runTestsWithSummary (#15789) (07f2f05)

🏡 Chores

  • prevent dev server from dirtying tracked files (#15826) (cb6f426)
  • plugin-search: clean up .DS_Store file and resulting empty images directory (#14506) (f6f73dd)

⚠️ BREAKING CHANGES

  • rename widget ComponentPath to Component for consistency (#15780) (f7d0d04)

    • Renames Widget.ComponentPath to Widget.Component and types it as PayloadComponentinstead ofstring`
    • This aligns dashboard widgets with every other component reference in (collections, globals, fields, admin components) - none of them path in the property name, and all of them are typed as PayloadComponent
    • Enables new typescript plugin to work for widget paths (the plugin uses PayloadComponent contextual type detection - string-typed properties were invisible to it)
  • ui: typo in CodeEditor export statement (#15795) (c5b2a91)

🤝 Contributors

v3.78.0

27 Feb 20:18
05e818e

Choose a tag to compare

v3.78.0 (2026-02-27)

🚀 Features


Feature Details

TypeScript Plugin for Component Paths - New @payloadcms/typescript-plugin validates PayloadComponent import paths directly in your IDE. It checks that referenced files and exports exist, provides autocomplete for file paths and export names, supports go-to-definition on component path strings, and understands all Payload path conventions including absolute paths, relative paths, tsconfig aliases, and package imports. #15779

screenshot.2026-02-26.at.15.55.40.mp4
pnpm add -D @payloadcms/typescript-plugin
{
  "compilerOptions": {
    "plugins": [{ "name": "next" }, { "name": "@payloadcms/typescript-plugin" }]
  }
}

Trash Out of Beta with Granular Delete Access - Trash is now a stable feature. Delete access control can now distinguish between trashing and permanently deleting — allowing you to permit users to soft-delete documents while restricting permanent deletion to admins. When data.deletedAt is being set, the operation is a trash; otherwise it's a permanent delete. #15210

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  trash: true,
  access: {
    delete: ({ req: { user }, data }) => {
      // Not logged in - no access
      if (!user) {
        return false
      }

      // Admins can do anything (trash or permanently delete)
      if (user.roles?.includes('admin')) {
        return true
      }

      // Regular users: check what operation they're attempting
      // If data.deletedAt is being set, it's a trash operation - allow it
      if (data?.deletedAt) {
        return true
      }

      // Otherwise it's a permanent delete - deny for non-admins
      return false
    },
  },
  fields: [
    // ...
  ],
}

Widget Fields (next, ui) - Dashboard widgets can now declare configurable fields, similar to Blocks. Widget data is editable from a new drawer UI when in dashboard editing mode. Full type generation is included — WidgetInstance<T> is generic with typed data and width, and WidgetServerProps is generic so widget components receive typed widgetData. #15700

Screen.Recording.2026-02-23.at.16.25.40.mov
import { buildConfig } from 'payload'

export default buildConfig({
  admin: {
    dashboard: {
      widgets: [
        {
          slug: 'sales-summary',
          ComponentPath: './components/SalesSummary.tsx#default',
          fields: [
            { name: 'title', type: 'text' },
            {
              name: 'timeframe',
              type: 'select',
              options: ['daily', 'weekly', 'monthly', 'yearly'],
            },
            { name: 'showTrend', type: 'checkbox' },
          ],
          minWidth: 'small',
          maxWidth: 'medium',
        },
      ],
    },
  },
})
import type { WidgetServerProps } from 'payload'

import type { SalesSummaryWidget } from '../payload-types'

export default async function SalesSummaryWidgetComponent({
  widgetData,
}: WidgetServerProps<SalesSummaryWidget>) {
  const title = widgetData?.title ?? 'Sales Summary'
  const timeframe = widgetData?.timeframe ?? 'monthly'

  return (
    <div className="card">
      <h3>
        {title} ({timeframe})
      </h3>
    </div>
  )
}

MCP Plugin Out of Beta (plugin-mcp) - @payloadcms/plugin-mcp is now stable and ready for production use. #15711

Virtual Field Filtering in MCP (plugin-mcp) - Virtual fields (virtual: true) are now automatically stripped from MCP tool input schemas and filtered from parsed data before create, update, and updateGlobal operations. This prevents non-stored fields from appearing as accepted MCP parameters. #15680

Markdown Transformer for Upload Nodes (richtext-lexical) - Upload nodes are now properly converted when using convertLexicalToMarkdown. Previously, upload nodes were silently dropped during markdown conversion. Now populated image uploads output ![alt text](/uploads/image.jpg), non-image uploads output link syntax, and non-populated uploads output a reference placeholder so data is never lost. #15630

Dashed Button Style (ui) - Adds a new dashed button style variant. Also replaces box-shadow with border on all buttons and fixes icon-only button padding. #15728

Button styles overview

Editable Query Presets from Form View (ui) - Query presets can now be created and edited directly from the document form view using a full WhereBuilder, column picker, and groupBy selector — no longer requiring the list view to build queries first. #15657

Screen.Recording.2026-02-17.at.18.15.34.mov

🐛 Bug Fixes

  • getFieldsToSign crashes when user missing group/tab fields (#15775) (9f0c101)
  • improve mobile touch support for dnd (#15771) (418bb92)
  • prevent silent data overwrites on concurrent edits (#15749) (7a3f43f)
  • preserve block metadata in mergeLocalizedData and filterDataToSelectedLocales (#15715) (6557292)
  • return 400 for malformed JSON request bodies (#15706) (4861fa1)
  • globals not updating updatedAt when saving drafts (#15764) (df17cb1)
  • return early if pasteURL is not defined (#15748) (23d52a0)
  • prevent req.file leak between sequential duplicate() calls on upload collections (#15620) (2baea2e)
  • sanitize filenames in storage adapters (#15746) (45bd2f1)
  • throw error for unknown query operators (#15739) (08226db)
  • preserve locale data in unnamed groups with localizeStatus (#15658) (38b8c68)
  • next: conditionally query snapshot field based on localization (#15693) (d5706ee)
  • plugin-import-export: update docs on jobs and basic usage as well as visibility (#15695) (a40210c)
  • plugin-mcp: use inline block schemas in JSON output (#15675) (a66e844)
  • plugin-multi-tenant: hasMany tenant fields double-wrap arrays in filterOptions (#15709) (aaddeac)
  • plugin-multi-tenant: return false instead of query when no tenants (#15679) ([f5a5bd8](https://github....
Read more

v3.77.0

18 Feb 19:39
71be0ca

Choose a tag to compare

v3.77.0 (2026-02-18)

🚀 Features

  • pass local API depth through to req.query.depth for consistency (#15023) (9a38469)
  • db-*: add customID arg to db.create (#15653) (0935824)
  • plugin-mcp: migrate from @vercel/mcp-adapter to mcp-handler (#15661) (24025fd)

Feature Details

Local API Depth Consistency - The depth option passed to Local API calls like payload.find() is now automatically set on req.query.depth. Previously, hooks relying on req.query.depth would behave differently between Local API and REST/GraphQL calls unless you manually passed req: { query: { depth: x } } in addition to depth: x. This change ensures consistent behavior across all API methods. #15023

Custom ID Support in db.create (db-*) - New customID argument on payload.db.create allows creating documents with a specific ID without requiring a custom ID field in your collection schema. #15653

payload.db.create({ collection: 'posts', customID: 'ce98d6c4-c3ab-45de-9dfc-bf33d94cc941', data: { } })

MCP Plugin Migration (plugin-mcp) - Migrates from the deprecated @vercel/mcp-adapter to mcp-handler and bumps @modelcontextprotocol/sdk to 1.25.2 addressing a security vulnerability. Exposes new handler options: disableSse, onEvent, and redisUrl. #15661

import { mcpPlugin } from '@payloadcms/plugin-mcp'

export default buildConfig({
  plugins: [
    mcpPlugin({
      // Optional: Enable SSE transport (disabled by default)
      disableSse: false,
      // Optional: Redis URL for SSE session management (defaults to REDIS_URL env)
      redisUrl: 'redis://localhost:6379',
      // Optional: Track MCP events for analytics/debugging
      onEvent: (event) => {
        console.log('MCP event:', event)
      },
    }),
  ],
})

🐛 Bug Fixes

  • hasMany text fields cannot be filtered with contains operator (#15671) (4513a05)
  • use consistent empty state styling between list and folder views (#15555) (8953b37)
  • populate previousValue correctly in afterChange hooks for nested lexical fields (#15623) (1cc3bb9)
  • add i18n support for dashboard edit mode buttons (#15564) (818e31d)
  • next: handle undefined fieldTab in version diff tabs (#15590) (bbacab8)
  • plugin-cloud-storage: ensure file data persists across operations (#15570) (6af3673)
  • plugin-cloud-storage: generateFileURL only ran when disablePayloadAccessControl was true (#15667) (6c5611c)
  • plugin-import-export: remove deprecated import (#15666) (733b1df)
  • plugin-import-export: export and import issues when using custom IDs (#15518) (7e2a3ab)
  • plugin-import-export: columns being duplicated when using toCSV hook (#15597) (28e07dc)
  • plugin-mcp: resolve union type fields failing in update tool (#15660) (9ae89dd)
  • plugin-multi-tenant: improve translation for "Tenant" (use "Mandant" instead of "Mieter") (#15537) (4d4033b)
  • plugin-multi-tenant: tenant selector not appearing after login (#15617) (dd09f67)
  • storage-r2: build error due to types issue in R2 Bucket type (#15670) (7d1e233)
  • ui: fix broken polymorphic join edit drawer (#15621) (d450e99)

📚 Documentation

🧪 Tests

  • trash e2e tests check URL before navigation completes (#15599) (7fe5a8c)

🏡 Chores

  • add md and mdx language block linting (#15309) (5415516)
  • bump playwright to fix vscode run test indicators (#15626) (f74d288)
  • only add publishAllLocales to publish when localizeStatus is enabled (#15610) (d57bc22)

🤝 Contributors

v3.76.1

11 Feb 18:34
3a486c5

Choose a tag to compare

v3.76.1 (2026-02-11)

🐛 Bug Fixes

  • use optional chaining for adminThumbnail size lookup to prevent crash (#15586) (6937eec)
  • non-image files should not recieve 0 bytes with useTempFiles (#15538) (a313627)
  • add CSP headers to SVG uploads to prevent XSS (#15506) (8283c25)
  • richtext-lexical: link tooltip overflows outside viewport with long URLs (#15584) (af6b1a1)
  • ui: prevent Tabs field crash when stored tabIndex exceeds tab count (#15588) (a9e296e)
  • ui: copy to locale function swallowing errors (#15562) (8ce62d8)
  • ui: ensure unpublish button only shows when drafts are enabled (#15459) (69dc5e6)

⚙️ CI

v3.76.0

09 Feb 21:30
5909064

Choose a tag to compare

v3.76.0 (2026-02-09)

🚀 Features

  • plugin-import-export: adds new exportLimit, importLimit and per collection limit control (#15405) (a7beeca)

🐛 Bug Fixes

  • drizzle: use dynamic import for typescript to avoid dependency in production (#15545) (98a756c)
  • live-preview-vue: update build config to compile as esm (#14293) (60c65ed)
  • next: drop support for Next.js versions with known CVEs, add canary 16.2.0 support (#15547) (2b3061a)
  • next: suppress webpack "Critical dependency" warning in dynamicImport (#15534) (6158489)
  • plugin-import-export: errors when import/export files were stored in a storage adapter such as S3 (#15441) (73a9650)
  • ui: tab error badge not counting required array validation errors (#15563) (0ce6193)
  • ui: folder view toggle button styles overridden due to equal specificity (#15544) (df42bec)
  • ui: remove clearData call in dropzone drop handler (#10475) (b4e6761)

📝 Templates

⚙️ CI

  • do not wait for generating int and e2e matrix (#15546) (de43402)

🏡 Chores

  • fix deprecation warning when running reinstall or clean:all monorepo script (#15535) (03bfaf4)
  • drizzle: add logs indicating which migration statements are generated (#15374) (306974d)

🤝 Contributors

v3.75.0

05 Feb 17:44
00e2ffb

Choose a tag to compare

v3.75.0 (2026-02-05)

🚀 Features

  • adds beforeNav and afterNav component slots (#15493) (f23a1df)
  • next: pass full initReq context to server functions and dashboard widgets (#15427) (ce13e97)

🐛 Bug Fixes

  • handle absolute paths correctly with tempFileDir upload option (#14436) (5ca9bd4)
  • ungenerated image sizes should not store original URL (#15454) (fa1cd62)
  • add safety check to redirects from external file URL uploads (#15458) (1041bb6)
  • sass warning not hidden during webpack build (#15442) (dec0ea7)
  • add collection property to auth documents, fixing multi tenancy access control issue (#15404) (d6aa6cc)
  • graphql: blocks return null with select: true (#15464) (c2baef4)
  • next: versions diff error when swapping blocks with relationship fields (#15478) (5ba0055)
  • next: export SlugField from the client dir not rsc (#15461) (6c07f3b)
  • next: sync modular dashboard widgets when server component re-renders (#15439) (5495b47)
  • plugin-ecommerce: variant creation blocked by variants in trash (#15449) (3f01682)
  • plugin-mcp: create and update resource tools now support point fields (#15381) (a28261d)
  • ui: extra padding rendering in list view when no description exists (#15507) (3ff6be4)
  • ui: remove slug field from rsc exports (#15480) (8f66035)

⚡ Performance

  • next: avoid re-calculating permissions in some server functions, pass missing args (#15428) (9c8be5c)

📚 Documentation

🎨 Styles

🧪 Tests

⚙️ CI

🏡 Chores

  • fix eslint config lookup in formatting hooks (#15516) (38a88b3)
  • remove duplicative agents.md, document ai tool compatibility (#15472) (6216f56)
  • remove template lockfiles (#15494) (362bf2f)
  • replace magic strings with centralized constants (#15475) (8422668)
  • claude post-write hook causes error when IDE checks output and doesn't apply formatting correctly (#15445) (033b943)
  • claude: add playwright mcp (#15447) (f15b9a3)
  • plugin-multi-tenant: use beforeNav instead of beforeNavLinks for tenant selector (#15499) (5d7d544)

🤝 Contributors

v3.74.0

30 Jan 16:32
de4fa0c

Choose a tag to compare

v3.74.0 (2026-01-30)

🚀 Features

  • thread override access in doc level hooks (#15421) (85d5263)
  • extend strictDraftTypes to all draft operations (#15292) (9239164)
  • add support for custom UnpublishButton component (#15400) (94254da)
  • storage-r2: client uploads using R2 multipart api (#14733) (5c38902)
  • ui: allows opting out of popup closing logic (#15407) (fb2b602)
  • ui: allows customizing Popup component portal className (#15406) (0f55464)

Override Access in Document-Level Hooks - Access the overrideAccess value inside collection and global hooks. Useful when hook logic needs to know whether access control was bypassed, such as when querying related documents up a hierarchy. #15421

export const Posts: CollectionConfig = {
  slug: 'posts',
  hooks: {
    beforeChange: [
      ({ overrideAccess, req }) => {
        if (overrideAccess) {
          // Access control was bypassed
        }
      },
    ],
  },
}

Extended strictDraftTypes to All Operations - When strictDraftTypes: true is enabled, TypeScript now enforces draft type safety across all Local API operations (not just queries). The draft option is forbidden for collections/globals without drafts enabled, preventing silent runtime behavior where draft flags are ignored. #15292

import { buildConfig } from 'payload'

export default buildConfig({
  typescript: {
    strictDraftTypes: true, // Enables compile-time draft enforcement
  },
  // ...
})

⚠️ Note: Generic collection slugs may require explicit type assertions when using draft options.


Custom UnpublishButton Component - Customize the UnpublishButton in collection and global configs, following the same pattern as PublishButton and SaveButton. Previously hardcoded. #15400

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    components: {
      edit: {
        UnpublishButton: '/components/CustomUnpublishButton',
      },
    },
  },
}

R2 Multipart Client Uploads (storage-r2) - Upload large files directly from the client using R2's multipart API. Files are split into smaller parts and uploaded separately, avoiding Cloudflare Worker memory limits. #14733


Popup Prevent Close Attribute (ui) - Add interactive elements inside popups without triggering close behavior by adding the data-popup-prevent-close attribute. #15407

<Popup>
  <button data-popup-prevent-close onClick={handleClick}>
    Click me without closing
  </button>
</Popup>

Popup Portal className (ui) - Customize the Popup component's portal container with the new portalClassName prop. #15406

<Popup portalClassName="my-custom-portal-class">
  {/* content */}
</Popup>

🐛 Bug Fixes

  • isolate payload-preferences by auth collection (#15425) (2dc2e7c)
  • traverseFields returning wrong parentPath dot notation for non-localised tabs (#15394) (99b051e)
  • widgets and other features failing with transitive dependency imports (#15392) (5561799)
  • replace deprecated scmp with crypto.timingSafeEqual (#15322) (2511c02)
  • find afterRead hooks should behave like findByID (#15357) (3e27155)
  • remove depth from count operation types (#15356) (dfc1600)
  • publish button incorrectly shown after saving draft when access denied (#15319) (e833fe6)
  • next: version view throws useLocale() server error (#15380) (2ce26fa)
  • next: ensure query preset from url is applied (#15323) (592f404)
  • next: ensure save preset button is not shown when there are no changes (#15320) (e9af097)
  • plugin-cloud-storage: prevent infinite loop when cropping media (#15393) (345a9c7)
  • plugin-cloud-storage: adds beforeChange hook to generate url on create (#15401) (d269d39)
  • richtext-slate: localized indicator not displaying in label (#15412) (126f713)
  • ui: use the formatAdminUrl function to generate unpublish url (#15375) (453e8a6)
  • ui: restore default columns after clearing query preset (#15360) (029699d)
  • ui: prevent globals crash with arrays fields when lock state user is undefined in handleDocumentLocking (#15259) (ea76ca0)
  • ui: getEntityConfig did not respect globalSlug if collectionSlug is undefined (#15362) (b54059c)

📚 Documentation

  • clarify beforeValidate and beforeChange hook data behavior (#15300) (ba9605e)
  • add payload.logger.error usage guidelines to CLAUDE.md (#15398) (cdbfda2)
  • updated redirects plugin integration docs and postgres connection troubleshooting (#15383) (9b2221e)
  • improve select jsdocs and empty select docs (#15336) (4181a12)

🧪 Tests

  • make integration tests for the fields and select suites faster (#15434) (26ba779)

📝 Templates

🔨 Build

⚙️ CI

  • enable retries for int and unit tests (#15397) (8b21263)
  • cache e2e prod preparation to run once instead of per-shard, various improvements and flake fixes (#15368) (2b3b9d5)
  • automatically shard int tests (#15367) (1041b15)
  • disable playwright tracing for first test runs, to improve performance and reduce flakes (#15337) (ab603c3)
  • automatically shard e2e tests (#15366) (2f19f8f)
  • add missing value property to outputs (#15338) (479b057)
  • bump monorepo Node.js version from 23.11.0 to 24.13.0 (#15364) (d95c365)
  • add linked PR feature to pop...
Read more

v3.73.0

23 Jan 20:50
b3796f5

Choose a tag to compare

v3.73.0 (2026-01-23)

🚀 Features

Feature Details

🔥 Next.js 16 Support - Full compatibility with Next.js 16, including Turbopack HMR and build support. Requires Next.js >16.1.1-canary.35 or 16.2.0+. Templates will be updated after Next.js 16.2.0 is released. Stable Next.js 16.1.* is not supported, as we depend on fixes released in the Next.js canary. Support for cache components will follow in a future release #14456

WAL Mode Support (db-sqlite) - Enable SQLite Write-Ahead Logging for improved concurrent read/write performance. Configurable synchronous mode and journal size limit. #15278

Busy Timeout Option (db-sqlite) - Set maximum wait time in milliseconds when the database is locked, preventing SQLITE_BUSY errors in high-concurrency scenarios. #15317

Predefined Migration for blocksAsJSON (drizzle) - Migrate existing projects to use blocksAsJSON: true with a single command. Automatically updates your Payload config and generates the required migration. #15257

pnpm payload migrate:create --file @payloadcms/db-postgres/blocks-as-json

Request Handler in Live Preview Hooks (live-preview) - The useLivePreview hook (React and Vue) now accepts a requestHandler argument, allowing customization of data fetching. Useful when your frontend proxies requests or uses external middleware. #15302

Select API for MCP Tools (plugin-mcp) - Find, Create, and Update tools for Globals and Collections now support the select API, reducing token usage and aligning with Payload's existing query capabilities. #15301

Native useEffectEvent (ui) - Uses React's native useEffectEvent when available (React 19.2.0+), falling back to the existing polyfill for older versions. #15304

🐛 Bug Fixes

  • select hasMany prevent duplicate values (#15218) (f4e8990)
  • orderable fractional indexing case-sensitivity issue with PostgreSQL (#14867) (ef27ad9)
  • find distinct sort on a different field (#15233) (e95f26d)
  • conditional tabs breaking in Next.js 16 due to unstable tab id (#15270) (f5a7a00)
  • correct previousValue and value in afterChange when using seo-plugin (#15253) (b6b6bab)
  • db-mongodb: fix projection handling for relationship fields in GraphQL queries with select (#14850) (ace3447)
  • drizzle: d1 sqlite IN querying of id when any other join is present in the query (#15290) (4f5a9c2)
  • next: relationship fields with maxDepth: 0 show "Untitled - ID" in diff view (#15305) (65238c5)
  • plugin-mcp: auto-detect basePath from Payload config routes (#15189) (dbc06f6)
  • richtext-lexical: internal links render as href="#" in versions view (#15308) (ab4102c)
  • sdk: correct return types with select (#15289) (db40d7b)
  • ui: diff view columns have unequal widths for nested fields causing text misalignment (#15330) (db72a65)
  • ui: upsertPreferences did not return preferences when creating new preferences (#15321) (94d5728)
  • ui: pass the locale to reorder endpoint in orderable table (#14839) (d6bb3de)

📚 Documentation

📝 Templates

  • upgrade website template and examples tailwind to v4 (#11197) (e77f9b6)

⚙️ CI

  • prevent rate limiting in release-commenter action (#15298) (71b35fa)

🏡 Chores

  • removes never implemented readDrafts access arg on globals (#15297) (12b679f)
  • export fractional indexing utilities (#15286) (02800b0)

🤝 Contributors