Setting Up Payload with Supabase for your Next.js App: A Step-by-Step Guide

Published On
How to set up Payload and Supabase
How to set up Payload and Supabase
In this post, we're going to walk you through how to set up Payload in combination with Supabase. This guide will walk you through the steps to integrate these two powerful tools seamlessly.

Why Use Supabase with Payload?

Payload requires a database to function, and in most cases, you'll also need a place to store your files. While Payload can store files on your local drive, this setup is not convenient for deployments, especially in serverless environments.

Supabase offers both a PostgreSQL database and multiple S3 storage buckets, making it an excellent choice for your project. Plus, Supabase's free plan provides a 500MB PostgreSQL database and 1GB of S3 storage, which should be sufficient for most small projects.

Getting Started

  1. Open your terminal and navigate to the folder where you want to create your project.
  2. Run the following command: npx create-payload-app@beta
  3. Name your project: You will be prompted to give your project a name. For this example, we'll use supabase-payload.
  4. Choose a project template: Select the blank template since we're not building a plugin.
  5. Select a database: Choose PostgreSQL. For now, use a local connection string, which we'll replace later.

Setting Up Supabase

  1. Sign up or log in to Supabase at supabase.com.
  2. Create a new project: Name it supabase-payload, set a database password (you can generate one automatically), and choose your region (e.g., Frankfurt).
  3. Obtain your connection string: Once the project setup is complete, click on Connect in the upper right corner to get your PostgreSQL connection string. Copy this string—you will use it to replace the local connection string in your environment variables at the next stage.

Configuring Payload

  1. Navigate to your local project: cd supabase-payload. And then open with VS Code: code .
  2. Update your environment variables (.env): Replace the local connection string with the Supabase connection string and set your database password.
  3. Start the development server: npm run dev Open http://localhost:3000 in your browser.

Access the admin panel at: http://localhost:3000/admin.

4. Create your first user: Follow the prompts to set up your admin user.

Adding Users and Collections

  1. Create users: Add a test user and verify that the users are saved in your Supabase database.
  2. Create a collection: For demonstration, we'll create a documents collection:
1
export const documents = {
2
slug: 'documents',
3
fields: [
4
{
5
name: 'name',
6
type: 'text',
7
label: 'Name',
8
required: true,
9
},
10
],
11
};
12

3. Ensure the configuration in payload.config.js: Add the following line to include your collection.

1
import path from 'path';
2
import { fileURLToPath } from 'url';
3
4
import { payloadCloud } from '@payloadcms/plugin-cloud';
5
import { postgresAdapter } from '@payloadcms/db-postgres'; // Updated to Postgres adapter
6
import { webpackBundler } from '@payloadcms/bundler-webpack';
7
import { lexicalEditor } from '@payloadcms/richtext-lexical'; // Using Lexical editor
8
import { buildConfig } from 'payload/config';
9
10
import Users from './collections/Users';
11
import Documents from './collections/Documents'; // Importing Documents collection
12
13
const filename = fileURLToPath(import.meta.url);
14
const dirname = path.dirname(filename);
15
16
export default buildConfig({
17
admin: {
18
user: Users.slug,
19
},
20
collections: [Users, Documents],
21
editor: lexicalEditor({}),
22
plugins: [payloadCloud()],
23
secret: process.env.PAYLOAD_SECRET || '',
24
typescript: {
25
outputFile: path.resolve(dirname, 'payload-types.ts'),
26
},
27
db: postgresAdapter({
28
pool: {
29
connectionString: process.env.DATABASE_URI || '',
30
},
31
}),
32
});
33

4. Adjust tsconfig.json if using JavaScript: If you're using JavaScript, you'll need to include JS files in your TypeScript configuration.

1
{
2
"compilerOptions": {
3
"paths": {},
4
"target": "ES2017"
5
},
6
"include": [
7
"next-env.d.ts",
8
"**/*.ts",
9
"**/*.tsx",
10
".next/types/**/*.ts",
11
"**/*.js", // If you're using JS, adjust your tsconfig file to also include JS files.
12
"**/*.jsx" // If you're using JS, adjust your tsconfig file to also include JS files.
13
],
14
"exclude": [
15
"node_modules"
16
]
17
}
18

Add this to your Payload config and restart the server: npm run dev

Finally, verify data in Supabase—add some documents and check your Supabase database to ensure they are saved correctly.

Setting Up S3 File Storage with Payload and Supabase

Let's install the S3 plugin:

  1. npm install @payloadcms/storage -s3 Since Payload is currently in beta (version 3 at the time of writing), you might encounter issues with peer dependencies. To resolve these, you can use the legacy-peer-deps flag. Alternatively, you could create an .npmrc file consisting of legacy-peer-deps=true.
  2. Configure the plugin: Add the following to your Payload config:

1
s3Storage({
2
collections: {
3
media: {
4
prefix: 'media',
5
}
6
},
7
bucket: process.env.S3_BUCKET,
8
config: {
9
forcePathStyle: true, // Important for using Supabase
10
credentials: {
11
accessKeyId: process.env.S3_ACCESS_KEY_ID,
12
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
13
},
14
region: process.env.S3_REGION,
15
endpoint: process.env.S3_ENDPOINT,
16
},
17
}),
18

I'm going to use it on a media collection, which we'll create shortly. We also need to give it a bucket name and a config with the accesskey, region, and endpoint. It's also important to force the path styles with Supabase.

3. Now let's create a media collection:

1
export const media = {
2
slug: 'media',
3
upload: true,
4
fields: [],
5
};
6

And now we need to add it to our Payload config.

1
import path from 'path';
2
import { fileURLToPath } from 'url';
3
4
import { payloadCloud } from '@payloadcms/plugin-cloud';
5
import { postgresAdapter } from '@payloadcms/db-postgres'; // database-adapter-import
6
import { webpackBundler } from '@payloadcms/bundler-webpack'; // bundler-import
7
import { lexicalEditor } from '@payloadcms/richtext-lexical'; // editor-import
8
import { buildConfig } from 'payload/config';
9
10
import Users from './collections/Users';
11
import Documents from './collections/Documents'; // Importing Documents collection
12
import Media from './collections/Media'; // Importing Media collection
13
import { s3Storage } from '@payloadcms/storage-s3'; // Importing S3 storage plugin
14
15
const filename = fileURLToPath(import.meta.url);
16
const dirname = path.dirname(filename);
17
18
export default buildConfig({
19
admin: {
20
user: Users.slug,
21
},
22
collections: [Users, Documents, Media], // Add the media collection here
23
editor: lexicalEditor({}),
24
// plugins: [payloadCloud()], // TODO: Re-enable when cloud supports 3.0
25
secret: process.env.PAYLOAD_SECRET || '',
26
typescript: {
27
outputFile: path.resolve(dirname, 'payload-types.ts'),
28
},
29
db: postgresAdapter({
30
pool: {
31
connectionString: process.env.DATABASE_URI || '',
32
},
33
}),
34
plugins: [
35
s3Storage({
36
collections: {
37
media: {
38
prefix: 'media',
39
},
40
},
41
bucket: process.env.S3_BUCKET,
42
config: {
43
forcePathStyle: true,
44
credentials: {
45
accessKeyId: process.env.S3_ACCESS_KEY_ID,
46
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
47
},
48
region: process.env.S3_REGION,
49
endpoint: process.env.S3_ENDPOINT,
50
},
51
}),
52
],
53
});
54

4. Restart the server.

5. Setup a bucket in Supabase: Create a new bucket in Supabase named supabase-payload and get your credentials (access key and secret access key).

6. Obtain your Supabase credentials:

  • Go to your Supabase project dashboard.
  • Navigate to Storage and create a new bucket named supabase-payload.
  • Set the bucket to either public or private based on your needs.
  • Navigate to Settings and find your endpoint, region, access key, and secret access key. Update environment variables: Add your Supabase credentials to your environment variables:

7. Update environment variables: Add your Supabase credentials to your environment variables (.env):

1
S3_BUCKET=
2
S3_ACCESS_KEY_ID=
3
S3_SECRET_ACCESS_KEY=
4
S3_REGION=
5
S3_ENDPOINT=

Restart the server.

8. Upload an image: Test the setup by uploading an image through the Payload admin panel and verify the upload in your Supabase storage.

This should provide a clear and comprehensive guide. If you encountered any confusion in this guide, please check out the full YouTube video. Leave us any thoughts on Discord or in the comments of the video.