This is a major release that includes a re-architecture of Payload from Express and a single-page React app to Next.js. In addition to this architectural change, we've also shipped a ton of large features, miscellaneous fixes, and DX improvements.
Architectural changes
- Payload now installs fully in any Next.js app router
- You can now deploy your entire project (frontend and backend) in one app
- Payload can now be deployed serverless on platforms like Vercel
- Everything Payload does now works seamlessly within any Next.js project
- You can now use the Payload Local API in Server Components and Server Functions
- Postgres, Live Preview, and Lexical have been marked as stable
- All Payload exports have been significantly cleaned up and organized
- Payload is now an ESM project
- Payload is now modular, and we now publish new packages
ui
,next
,translations
, andgraphql
- The Payload config is now server-side only, and works in any Node environment
- Server-side HMR works out of the box - removing the need for
nodemon
Large features
- Join field - bi-directional relationships, more control over the database schema, and more
- Select API - select specific fields when querying using Local API
- Jobs Queue - background jobs fully supported in Payload with no third-party dependencies
- Populate / DefaultPopulate API - determine which fields should be retrieved when Payload populates relationships
- Lexical blocks and inline blocks - easily make Payload Blocks available in Lexical as custom rich text features
- SQLite database adapter now available
- Vercel Postgres database adapter released, specifically for serverless deploys on Vercel
- Live Preview server components support
- Admin UI has been refreshed
hasMany
upload fields are now supported- Bulk upload has been added
- Document Locking pattern has been implemented, which shows if someone is currently editing a document
- Ability to publish individual locales one at a time has been added
- Lexical now has Table support
Small but still important features
- New Payload logo (thanks Candycode!)
- New Resend email adapter is now available
- Postgres now saves single, monomorphic relationships directly in a column rather than in
_rels
table - GraphQL has been abstracted into a specific Next.js route handler, and no longer affects Payload initialization at all
- React Compiler has been introduced into Payload build pipeline
- You can now run migrations on init, rather than only in CI (helpful for long-running servers)
- New Local API operations -
count
,countVersions
,countGlobalVersions
,upsert
- Adds
baseListFilter
function to allow enforced list view filters based on user - Lexical fixed toolbar option has been added
- Optimized the way that relational DBs store relations
- Postgres point field is now supported
- Postgres deep JSON querying is now supported
- Cuztomize Drizzle schema by passing in your own, which is handled outside of Payload
- Fully typed i18n
t
function - Focal point data is now stored on uploads
- Adds ability to login with username rather than email
- New pattern for passing custom server / client props to custom components
- Email adapter pattern, including optimized Resend HTTP client
- Reduced / optimized the shape of
/access
permissions results - Allows sorting by multiple fields
- MongoDB now saves ObjectID for relationships
- Adds more control over log level customization
- Downgrades common errors like NotFound or Forbidden to info
- Swaps out
react-toastify
forsonner
- True "virtual" fields via
virtual: true
- Adds ability to customize filenames before upload
- Adds locale indicators to localized field labels
- Scope all payload css to payload-default layer
- Document duplicate / delete from drawers
⚠️ BREAKING CHANGES
This release includes breaking changes. In order to update from version 2 to 3, please review the migration docs.
🤝 Contributors
- James Mikrut (@jmikrut)
- Elliot DeNolf (@denolfe)
- Dan Ribbens (@DanRibbens)
- Said Akhrarov (@akhrarovsaid)
- Germán Jabloñski (@GermanJablo)
- Sophia Michelle Andren (@sandren)
- Jarrod Flesch (@JarrodMFlesch)
- Patrik (@PatrikKozak)
- Nate (@ncaminata)
- mattddean (@mattddean)
- Sasha (@r1tsuu)
- Jacob Fletcher (@jacobsfletch)
- Mikkel Wied Frederiksen (@mikkelwf)
- Alessio Gravili (@AlessioGr)
- Paul (@paulpopus)
- Tobias Odendahl (@tak-amboss)
- Jessica Chowdhury (@JessChowdhury)
- Ruy Monteiro (@ruymon)
- Nathan Clevenger (@nathanclevenger)
- Kendell Joseph (@kendelljoseph)
- Steve (@steventsvetkov)
- Mikkel Madsen (@miguel2650)
- Tylan Davis (@tylandavis)
- Javier (@javierlinked)
- Timothy Choi (@tyteen4a03)
- Andreas Bernhard (@abernh)
- Friggo (@MrFriggo)
- Jesper We (@JesperWe)
- vahacreative (@vahacreative)
- Manuel Leitold (@agrippa1994)
- Gregor Gabrič (@GregorGabric)
- Konsequanzheng (@Konsequanzheng)
- Brandon Kocur (@Brandoko)
- Anders Semb Hermansen (@andershermansen)
- Hristiyan Dodov (@hdodov)
- MotorcycleEnjoyer (@MotorcycleEnjoyer)
- Because789 (@Because789)
- Ante (@azivkovi)
- Mike Bailey (@mykz)
- Riley Pearce (@rilrom)
- Louis Ba (@muyunz)
- gervickas.js (@wellitongervickas)
- Frank Omondi (@Dofften)
- Thành Trang (@trangcongthanh)
- Victor Winberg (@VictorWinberg)
- Florian Quiblier (@fofoy)
- Christoffer Hasselberg (@stofolus)
- Hampus Wallentin Olsen (@hampusolsen)
- Bruno Crosier (@brunocrosier)
- Alexander (@Arctomachine)
- Francisco Lourenço (@franciscolourenco)
- Giuseppe Chiruzzi (@xfloor)
- Ritsu (@r1tsuu)
- Willy Brauner (@willybrauner)
- Michel v. Varendorff (@mvarendorff)
- Lynn Dylan Hurley (@lynndylanhurley)
- Hulpoi George-Valentin (@GeorgeHulpoi)
- Jasper Beaurain (@JasperBeaurain)
- Wilson (@WilsonLe)
- Harley Salas (@HarleySalas)
- Frederic Perron (@FredPerr)
- Viet-Tien (@nvti)
- Patryk Kowalczyk (@Patryk-Kowalczyk)
- Leo Hilsheimer (@linobino1)
- zvizvi (@zvizvi)
- Francis Turmel (@fturmel)