made with
payload
  • Showcases
  • Plugins
  • Creators
  • Tutorials
  • Templates
  • Videos

Not affiliated with PayloadCMS. Made by paul

  • Contact
  • Submit an entry
  • Releases
  • Stats
Back to Releases

v3.74.0

Version v3.74.0Minor Release
Released:

January 30, 2026

Type:

New features, backward compatible

GitHub:View Release
Download TarballDownload ZIP

Release Notes

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
}
},
],
},
}
ts

--- 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
},
// ...
})
ts

⚠️ 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',
},
},
},
}
ts

--- 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>
tsx

--- 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>
tsx

πŸ› 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

  • deps: bump Next.js versions (#15365) (5658ec2)

πŸ”¨ Build

  • add node-gyp for native module rebuilds (#15396) (50c087f)

βš™οΈ 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 popular-issues action (#15355) (614f13c)

🏑 Chores

  • export getSafeFileName utility (#15424) (6b45fee)
  • replace rmdirSync to rmSync (#15420) (17c0a3f)
  • claude: add respond-to-discussion-features claude command (#15391) (1f7fe63)
  • deps: bump form-data, tar, wrangler, and @opennextjs/cloudflare dependencies (#15435) (5875cd0)
  • deps: bump tsx (#15363) (7043e3f)
  • plugin-multi-tenant: removes basePath arg (#15202) (bd80784)
  • ui: move unpublish actions into document controls dropdown (#15417) (99d61db)

🀝 Contributors

  • Ricardo Tavares (@rjgtav)
  • Patrik (@PatrikKozak)
  • German Jablonski (@GermanJablo)
  • Jessica Rynkar (@jessrynkar)
  • Jarrod Flesch (@JarrodMFlesch)
  • Tobias Odendahl (@tak-amboss)
  • Paul (@paulpopus)
  • Elliot DeNolf (@denolfe)
  • Sean Zubrickas (@zubricks)
  • Alessio Gravili (@AlessioGr)
  • Georg Schelkshorn (@GeorgS)
  • Muhammad Hassaan Farooq (@Muhammad-Hassaan-Farooq)
  • RajeshKumar11 (@RajeshKumar11)
Browse All ReleasesView on GitHub