payload-starter

Next.js 16 and Payload 3 starter with PostgreSQL, role-based admin access, shadcn/ui and SEO helpers

payload-starter preview

Overview

Summary generated from the README

A general-purpose starter combining Next.js 16 App Router with Payload CMS 3 and a PostgreSQL database. It includes Users, Media and Posts collections, an admin and user role model, and a Tailwind CSS 4 frontend built on shadcn/ui. Media is stored in Vercel Blob by default, with the S3 storage package installed for switching to S3 or R2. Requires Node 20.9 or newer, pnpm and a PostgreSQL database.

Features

  • Users collection with admin and user roles gating admin panel access
  • Posts collection with Lexical rich text and optional SEO override fields
  • Central SEO helpers for metadata, sitemap, robots and JSON-LD structured data
  • Media uploads with Sharp optimization stored in Vercel Blob, S3 or R2 ready
  • REST and GraphQL APIs plus auto-generated TypeScript types
  • Vitest setup, security headers and Docker support

Good for

  • Starting a new Payload 3 project on Next.js with PostgreSQL and a clean frontend
  • Building a content site or blog that needs SEO metadata and structured data from day one
  • Creating a base project to extend with a separate user-facing authentication provider

From the author

A starter template to get started with Payload 3.0

Get started

This repository is a GitHub template: create your own copy of it in one click.

Create a repository from this template

README

Payload App Starter

A modern, open-source starter kit built with Next.js 16 and Payload CMS 3. Ships with the Payload admin panel, a PostgreSQL-backed CMS, role-based admin access, and a clean Next.js frontend — no custom SaaS auth layer to rip out.

Payload Starter

Demo

payloadstarter.dev

Want user-facing authentication? These sibling templates add a full auth layer on top of the same foundation:

Features

Payload CMS, batteries included

  • Payload admin panel at /admin with its own built-in authentication
  • Role-based admin access control (admin / user) on the Users collection
  • PostgreSQL via the official Payload adapter
  • Auto-generated, end-to-end TypeScript types from your collections
  • Media uploads with Sharp optimization, stored in Vercel Blob (S3/R2-ready)
  • REST API at /api and GraphQL at /api/graphql
  • SEO-ready public site with shared metadata helpers, sitemap, robots, JSON-LD, and post-level SEO overrides

Modern Tech Stack

CategoryTechnology
FrameworkNext.js 16.2 with App Router
Runtime UIReact 19.2
CMSPayload CMS 3.85
LanguageTypeScript 5.7
DatabasePostgreSQL
StylingTailwind CSS 4
Componentsshadcn/ui + Radix UI
StorageVercel Blob by default, S3/R2-ready
TestingVitest
Package Managerpnpm 10.12

Developer Experience

  • Server-first architecture with React Server Components
  • Auto-generated TypeScript types from Payload collections
  • typecheck and test scripts for a green baseline
  • Reusable design system components (@/components/ds)
  • Central SEO config driven by APP_URL
  • Built-in security headers
  • Docker support included
  • Vercel deployment ready

Quick Start

Prerequisites

  • Node.js: v20.9.0 or newer
  • Package Manager: pnpm 10.12.4
  • Database: PostgreSQL
  • Storage: Vercel Blob for media uploads, or configure S3/R2

Installation

# Clone the repository
git clone https://github.com/brijr/payload-starter.git
cd payload-starter

# Use the pnpm version pinned in package.json
npm install -g [email protected]

# Install dependencies
pnpm install

# Set up environment variables
cp .env.example .env
# Edit .env with your credentials

# Start the development server
pnpm dev

Visit http://localhost:3000 to see the frontend, and http://localhost:3000/admin for the Payload admin panel. The first account you create at /admin becomes your CMS user — set its role to admin to access the panel.

Available Scripts

CommandDescription
pnpm devStart development server
pnpm devsafeStart dev server (clears .next cache first)
pnpm buildBuild for production
pnpm startStart production server
pnpm lintRun ESLint
pnpm typecheckType-check with tsc --noEmit
pnpm testRun the Vitest suite once
pnpm test:watchRun Vitest in watch mode
pnpm payloadAccess Payload CLI
pnpm generate:typesGenerate TypeScript types from collections
pnpm generate:importmapGenerate Payload import map

Project Structure

src/
├── app/                      # Next.js App Router
│   ├── (frontend)/           # Frontend routes
│   │   └── (site)/           # Public site routes
│   └── (payload)/            # Payload CMS admin + API routes
│       ├── admin/            # Admin panel UI
│       └── api/              # Payload REST + GraphQL endpoints
├── collections/              # Payload collections (Users, Media)
│   └── Posts.ts              # Publishable posts with SEO override fields
├── components/
│   ├── site/                 # Site components (header, footer)
│   ├── theme/                # Theme provider and toggle
│   ├── ui/                   # shadcn/ui components
│   ├── rich-text.tsx         # Payload Lexical rich text renderer
│   ├── structured-data.tsx   # JSON-LD script renderer
│   └── ds.tsx                # Design system exports
├── hooks/                    # React hooks (use-mobile, ...)
├── lib/
│   ├── seo.ts                # Shared metadata, URL, sitemap, and JSON-LD helpers
│   ├── seo.test.ts           # SEO helper tests
│   ├── utils.ts              # Utility functions (cn, ...)
│   └── utils.test.ts         # Vitest smoke test
├── payload.config.ts         # Payload CMS configuration
└── payload-types.ts          # Auto-generated types

Environment Variables

Create a .env file in the root directory:

Required to Run

# Public app URL used for metadataBase, canonical URLs, sitemap, robots, and JSON-LD
APP_URL=http://localhost:3000

# Database (PostgreSQL)
DATABASE_URI=postgres://user:password@localhost:5432/dbname

# Payload CMS
PAYLOAD_SECRET=your-secure-secret-key-min-32-chars

Required for Media Uploads

Vercel Blob is preconfigured as the default media storage backend.

# Storage (Vercel Blob)
BLOB_READ_WRITE_TOKEN=vercel_blob_xxxxxx

Optional Storage Providers

The S3 storage package is installed for Cloudflare R2 or AWS S3. To switch providers, update src/payload.config.ts to use @payloadcms/storage-s3, then add the relevant credentials:

R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET=your-bucket-name
R2_ENDPOINT=https://your-endpoint.r2.cloudflarestorage.com

Route Organization

Route PatternAccessDescription
/(site)/*PublicMarketing pages, public content
/(payload)/*Admin loginPayload CMS admin interface
/api/*VariesPayload REST API
/api/graphqlVariesGraphQL endpoint

SEO Setup

SEO is centralized in src/lib/seo.ts so new projects can change the site name, default description, canonical host, and social images in one place.

  • Set APP_URL to the public origin for each environment. It powers metadataBase, canonical URLs, Open Graph URLs, robots.txt, sitemap.xml, and JSON-LD.
  • Root metadata in src/app/(frontend)/layout.tsx uses shared defaults, including title templates, robots directives, Open Graph, and Twitter card metadata.
  • Public pages use createMetadata() or createArticleMetadata() for canonical, Open Graph, and Twitter metadata.
  • src/app/(frontend)/(site)/sitemap.ts includes /, /posts, and published posts from Payload when DATABASE_URI is configured.
  • src/app/robots.ts allows the public site and disallows /admin and /api.
  • StructuredData renders escaped JSON-LD. The root layout emits WebSite and Organization schema; post pages emit Article and BreadcrumbList schema.
  • Posts include optional meta.title, meta.description, and meta.image fields. If left blank, metadata falls back to the post title, excerpt, hero image, and site defaults.

Authentication

Authentication is handled entirely by Payload CMS's built-in auth on the Users collection — there is no custom user-facing auth layer.

  • Sign in at /admin to reach the CMS.
  • Access to the admin panel is gated by the isAdmin access control in src/collections/Users.ts, which checks user.role === 'admin'.
  • Payload manages password hashing (bcrypt), the auth cookie, CSRF protection, and rate limiting for you.

To add user-facing login/registration, layer an auth provider on top (see the payload-clerk / payload-workos sibling templates) or build against Payload's local API and authentication docs.

Storage Configuration

Vercel Blob (Default)

Already configured. Just add BLOB_READ_WRITE_TOKEN to your environment.

Cloudflare R2 / AWS S3

  1. Add an @payloadcms/storage-s3 plugin configuration in payload.config.ts
  2. Disable or remove the Vercel Blob storage plugin
  3. Add R2/S3 credentials to your environment

Security

FeatureImplementation
Admin authPayload built-in (HTTP-only cookies)
CSRF ProtectionBuilt into Payload
Password Hashingbcrypt via Payload
Access Controlrole-based on the Users collection
Security HeadersConfigured in next.config.mjs
Rate LimitingBuilt into Payload auth endpoints

Common Tasks

Adding a New Collection

# 1. Create collection file
# /src/collections/Posts.ts

# 2. Add to payload.config.ts
# collections: [Users, Media, Posts]

# 3. Generate types
pnpm generate:types

Adding UI Components

# shadcn/ui components are in /src/components/ui/
# Import layout + prose primitives from the design system:
import { Section, Container, Nav } from '@/components/ds'

Writing Tests

Vitest is configured out of the box. Co-locate *.test.ts files next to the code they cover (see src/lib/utils.test.ts) and run pnpm test.

Deployment

  1. Push your code to GitHub
  2. Import the repository in Vercel
  3. Configure DATABASE_URI, PAYLOAD_SECRET, APP_URL, and BLOB_READ_WRITE_TOKEN
  4. Deploy

Docker

# Build the image
docker build -t payload-starter .

# Run the container
docker run -p 3000:3000 --env-file .env payload-starter

See README.docker.md for Docker Compose development setup.

Troubleshooting

Next.js Cache Issues

pnpm devsafe  # Clears .next cache and starts dev server

Type Errors After Collection Changes

pnpm generate:types

Database Connection Issues

  • Verify DATABASE_URI format: postgres://user:password@host:5432/database
  • Ensure PostgreSQL is running
  • Check firewall/network settings

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments


Created by brijr

Claim this template

More Starters & boilerplates templates

payload-cms-boilerplate screenshot

payload-cms-boilerplate

Blank Payload 3 and Next.js 16 starter with Postgres, Tailwind, shadcn/ui primitives and a built-in SEO module

19
v3
Next.js
Updated 2 months ago
nextload screenshot

nextload

Next.js and Payload boilerplate with Better Auth, blog, cart, runtime theming and hybrid caching

1
v3
Next.js
Updated 2 weeks ago
payload-v4-admin-starter screenshot

payload-v4-admin-starter

Payload v4 beta website starter with configurable admin dashboard widgets and a custom semantic admin theme

1
v4
Next.js
Updated Yesterday