This package contains a set of utilities to allow Payload to be deployed seamlessly, serverless, within an existing NextJS project. It adds the Payload admin UI into the NextJS /app
folder and adds all Payload endpoints into the pages/api
folder.
To do so, this package exposes a few different helpers. To get started, follow the steps below:
npm install @payloadcms/next-payload payload
# or
yarn add @payloadcms/next-payload payload
npx next-payload install
# or
yarn next-payload install
# mongo connection string
MONGODB_URI=mongodb://localhost/create-next-app-serverless
# payload secret
PAYLOAD_SECRET=SOME_SECRET
# path to your payload.config file
PAYLOAD_CONFIG_PATH=payload/payload.config.ts
Payload needs to inject some requirements into your Next config in order to function properly. To install withPayload
, you need to import it into your next.config.js
file. Here's an example:
// next.config.js
const path = require('path');
const { withPayload } = require('@payloadcms/next-payload');
module.exports = withPayload({
// your Next config here
}, {
// The second argument to `withPayload`
// allows you to specify paths to your Payload dependencies.
// Point to your Payload config (Required)
configPath: path.resolve(__dirname, './payload/payload.config.ts'),
// Point to custom Payload CSS (optional)
cssPath: path.resolve(__dirname, './css/my-custom-payload-styles.css'),
// Point to your exported, initialized Payload instance (optional, default shown below`)
payloadPath: path.resolve(process.cwd(), './payload/payloadClient.ts'),
});
And then you're done. Have fun!
The payload/payloadClient.ts
file will be added for you after running yarn next-payload install
(step 2). You can import getPayloadClient
from that file from within server components to leverage the Payloads Local API. The Local API does not use REST or GraphQL, and runs directly on your server talking directly to your database, which saves massively on HTTP-induced latency.
Here is an example:
// app/[slug]/page.tsx
import React from "react";
import { notFound } from "next/navigation";
import { getPayloadClient } from "../../payload/payloadClient";
const Page = async ({ params: { slug } }) => {
const payload = await getPayloadClient();
const pages = await payload.find({
collection: "pages",
where: {
slug: {
equals: slug || "home",
},
},
});
const page = pages.docs[0];
if (!page) return notFound();
return <h1>Hello, this is the "{page.slug}" page!</h1>;
};
export async function generateStaticParams() {
const payload = await getPayloadClient();
const pages = await payload.find({
collection: "pages",
limit: 0,
});
return pages.docs.map(({ slug }) => ({ slug }));
}
export default Page;
With the nature of serverless functions, you are bound to encounter "cold start" delays when your serverless functions spin up for the first time. Once they're "warm", the problem will go away for a few minutes until the functions become dormant again. But there's little that this package can do about that issue, unfortunately.
If you'd like to avoid cold starts with your Payload API, you can deploy on a server-based platform like Payload Cloud instead.
To deploy Payload on Vercel, you'll need to configure additional vendors for the following:
- Database (MongoDB Atlas)
- File storage (AWS S3 or similar) with Payload's Cloud Storage Plugin
- Email service (Resend, Sendgrid)
If you don't want to go out and sign up for a separate file hosting service, you can just use Payload Cloud, which gives you file storage, a MongoDB Atlas database, email service by Resend, and lots more.