Alternative solution to https://github.com/payloadcms/payload/pull/11104. Big thanks to @andershermansen and @GermanJablo for kickstarting work on a solution and bringing this to our attention. This PR copies over the live-preview test suite example from his PR. Fixes https://github.com/payloadcms/payload/issues/5285, https://github.com/payloadcms/payload/issues/6071 and https://github.com/payloadcms/payload/issues/8277. Potentially fixes #11801 This PR completely gets rid of our client-side live preview field traversal + population and all logic related to it, and instead lets the findByID endpoint handle it. The data sent through the live preview message event is now passed to findByID via the newly added `data` attribute. The findByID endpoint will then use this data and run hooks on it (which run population), instead of fetching the data from the database. This new API basically behaves like a `/api/populate?data=` endpoint, with the benefit that it runs all the hooks. Another use-case for it will be rendering lexical data. Sometimes you may only have unpopulated data available. This functionality allows you to then populate the lexical portion of it on-the-fly, so that you can properly render it to JSX while displaying images. ## Benefits - a lot less code to maintain. No duplicative population logic - much faster - one single API request instead of one request per relationship to populate - all payload features are now correctly supported (population and hooks) - since hooks are now running for client-side live preview, this means the `lexicalHTML` field is now supported! This was a long-running issue - this fixes a lot of population inconsistencies that we previously did not know of. For example, it previously populated lexical and slate relationships even if the data was saved in an incorrect format ## [Method Override (POST)](https://payloadcms.com/docs/rest-api/overview#using-method-override-post) change The population request to the findByID endpoint is sent as a post request, so that we can pass through the `data` without having to squeeze it into the url params. To do that, it uses the `X-Payload-HTTP-Method-Override` header. Previously, this functionality still expected the data to be sent through as URL search params - just passed to the body instead of the URL. In this PR, I made it possible to pass it as JSON instead. This means: - the receiving endpoint will receive the data under `req.data` and is not able to read it from the search params - this means existing endpoints won't support this functionality unless they also attempt to read from req.data. - for the purpose of this PR, the findByID endpoint was modified to support this behavior. This functionality is documented as it can be useful for user-defined endpoints as well. Passing data as json has the following benefits: - it's more performant - no need to serialize and deserialize data to search params via `qs-esm`. This is especially important here, as we are passing large amounts of json data - the current implementation was serializing the data incorrectly, leading to incorrect data within nested lexical nodes **Note for people passing their own live preview `requestHandler`:** instead of sending a GET request to populate documents, you will now need to send a POST request to the findByID endpoint and pass additional headers. Additionally, you will need to send through the arguments as JSON instead of search params and include `data` as an argument. Here is the updated defaultRequestHandler for reference: ```ts const defaultRequestHandler: CollectionPopulationRequestHandler = ({ apiPath, data, endpoint, serverURL, }) => { const url = `${serverURL}${apiPath}/${endpoint}` return fetch(url, { body: JSON.stringify(data), credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-Payload-HTTP-Method-Override': 'GET', }, method: 'POST', }) } ``` --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211124793355068 - https://app.asana.com/0/0/1211124793355066
Explore the Docs · Community Help · Roadmap · View G2 Reviews
Important
🎉 We've released 3.0! Star this repo or keep an eye on it to follow along.
Payload is the first-ever Next.js native CMS that can install directly in your existing /app folder. It's the start of a new era for headless CMS.
Benefits over a regular CMS
- Deploy anywhere, including serverless on Vercel for free
- Combine your front+backend in the same
/appfolder if you want - Don't sign up for yet another SaaS - Payload is open source
- Query your database in React Server Components
- Both admin and backend are 100% extensible
- No vendor lock-in
- Never touch ancient WP code again
- Build faster, never hit a roadblock
Quickstart
Before beginning to work with Payload, make sure you have all of the required software.
pnpx create-payload-app@latest
If you're new to Payload, you should start with the website template (pnpx create-payload-app@latest -t website). It shows how to do everything - including custom Rich Text blocks, on-demand revalidation, live preview, and more. It comes with a frontend built with Tailwind all in one /app folder.
One-click templates
Jumpstart your next project by starting with a pre-made template. These are production-ready, end-to-end solutions designed to get you to market as fast as possible.
🌐 Website
Build any kind of website, blog, or portfolio from small to enterprise. Comes with a fully functional front-end built with RSCs and Tailwind.
We're constantly adding more templates to our Templates Directory. If you maintain your own template, consider adding the payload-template topic to your GitHub repository for others to find.
✨ Features
- Completely free and open-source
- Next.js native, built to run inside your
/appfolder - Use server components to extend Payload UI
- Query your database directly in server components, no need for REST / GraphQL
- Fully TypeScript with automatic types for your data
- Auth out of the box
- Versions and drafts
- Localization
- Block-based layout builder
- Customizable React admin
- Lexical rich text editor
- Conditional field logic
- Extremely granular Access Control
- Document and field-level hooks for every action Payload provides
- Intensely fast API
- Highly secure thanks to HTTP-only cookies, CSRF protection, and more
🗒️ Documentation
Check out the Payload website to find in-depth documentation for everything that Payload offers.
Migrating from v2 to v3? Check out the 3.0 Migration Guide on how to do it.
🙋 Contributing
If you want to add contributions to this repository, please follow the instructions in contributing.md.
📚 Examples
The Examples Directory is a great resource for learning how to setup Payload in a variety of different ways, but you can also find great examples in our blog and throughout our social media.
If you'd like to run the examples, you can use create-payload-app to create a project from one:
npx create-payload-app --example example_name
You can see more examples at:
🔌 Plugins
Payload is highly extensible and allows you to install or distribute plugins that add or remove functionality. There are both officially-supported and community-supported plugins available. If you maintain your own plugin, consider adding the payload-plugin topic to your GitHub repository for others to find.
🚨 Need help?
There are lots of good conversations and resources in our Github Discussions board and our Discord Server. If you're struggling with something, chances are, someone's already solved what you're up against. 👇

