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.78.0

Version v3.78.0Minor Release
Released:

February 27, 2026

Type:

New features, backward compatible

GitHub:View Release
Download TarballDownload ZIP

Release Notes

v3.78.0 (2026-02-27)

πŸš€ Features

  • typescript plugin for import paths (#15779) (7639664)
  • move trash out of beta and delete access can now be limited to trash only (#15210) (2347cd9)
  • next, ui: widget fields (#15700) (0a123b5)
  • plugin-mcp: out of beta (#15711) (1b19d5f)
  • plugin-mcp: ignore virtual fields in create and update operations (#15680) (cc8f888)
  • richtext-lexical: add markdown transformer for upload nodes (#15630) (4af5a85)
  • ui: adds dashed button style (#15728) (d570787)
  • ui: make query-presets editable from the form view (#15657) (575f8e9) ---

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 https://github.com/user-attachments/assets/2a8a8f73-a8fd-4e79-9dc4-795d817b5b75

pnpm add -D @payloadcms/typescript-plugin
bash
{
"compilerOptions": {
"plugins": [{ "name": "next" }, { "name": "@payloadcms/typescript-plugin" }]
}
}
json

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: [
// ...
],
}
ts

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 https://github.com/user-attachments/assets/b24d3635-8635-4d5f-84af-a6dcf801aa4f

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

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, non-image uploads output link syntax, and non-populated uploads output a reference placeholder so data is never lost. [#15630](https://github.com/payloadcms/payload/pull/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

Image from GitHub release

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 https://github.com/user-attachments/assets/d25b447b-c942-47ae-8878-47bd17a8a7fb ---

πŸ› 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)
  • richtext-lexical: bump acorn to resolve type mismatch with transitive dep (#15791) (801e851)
  • richtext-lexical: link markdown regex should not match similar looking image markdown (#15713) (0a0afb0)
  • richtext-lexical: use headingLevel in danish heading label (#15685) (ad4c0f6)
  • richtext-lexical: strip server-only properties from blocks in lexical client schema map (#15756) (c05ace2)
  • templates: ecommerce find my order access functionality to use email (#15736) (b317eaa)
  • ui: array field add button margin not applying consistently (#15773) (ee298f5)
  • ui: respect custom Cell components on richText fields in list view (#15762) (139cf3e)
  • ui: use correct translation key for collection version restore modal (#15757) (c1892eb)
  • ui: encode HTML special characters in version diff view (#15747) (30fee83)
  • ui: flash of border on list selection buttons (#15735) (7f3c6c8)

πŸ›  Refactors

  • extract regex escape pattern into shared utility (#15676) (8ce389e)
  • plugin-mcp: reduced code and de-duplication (#15705) (039e6c9)

🎨 Styles

  • richtext-lexical: lists and quotes have inconsistent letter spacing (#15682) (f2397a8)

πŸ§ͺ Tests

  • fix flaky versions tests timing out on link clicks before hydration (#15790) (02da3fd)
  • fix flaky lexical code block test with incorrect error expectations (#15776) (4e3e780)
  • trash e2e list view clicks timing out in CI (#15778) (fd81fd5)
  • fix flaky localization tests with race conditions (#15777) (bda5d0d)
  • bulk upload button clicks timeout in CI (#15703) (8228a7d)
  • field update access control test times out locally (#15691) (78e8e14)
  • fix flaky account unlock test in postgres-uuid and custom-schema (#15696) (e3a76e3)
  • fix flaky lexical e2e navigation timeouts and drawer clicks (#15694) (9ca5cda)
  • fix flaky access-control bulk delete tests failing due to timing issues (#15692) (558345b)
  • fix flaky drawer open and column sort timing issues (#15677) (00f763b)

πŸ“ Templates

  • fix cloudflare logger error in with-cloudflare-d1 template (#15752) (8791a72)
  • ecommerce add missing access control on collections (#15744) (c74d91d)
  • fix ecommerce webhooks url and update docs on using stripe webhooks (#15681) (677596c)

🏑 Chores

  • make test:e2e agent-friendly with --grep support and dev server reuse (#15755) (929203c)
  • deps: bump next.js canary in monorepo (#15708) (e3d8a94)
  • plugin-mcp: improve schema sanitization and test coverage (#15704) (7e20b5c)
  • templates: bump versions to 3.77.0 (#15678) (e26df27)

🀝 Contributors

  • Elliot DeNolf (@denolfe)
  • Alessio Gravili (@AlessioGr)
  • Patrik (@PatrikKozak)
  • Sean Zubrickas (@zubricks)
  • Benedikt RΓΆtsch (@axe312ger)
  • Shobhit Singhal (@shobhitsinghal624)
  • The Mavik (@themavik)
  • Divyesh Jain (@divyesh123-jain)
  • Paul (@paulpopus)
  • German Jablonski (@GermanJablo)
  • Jens Becker (@jhb-dev)
  • Jarrod Flesch (@JarrodMFlesch)
  • Jessica Rynkar (@JessRynkar)
  • Kendell (@kendelljoseph)
  • Varun Chawla (@veeceey)
Browse All ReleasesView on GitHub