Payload CMS Starter Review 2026: Content-First SaaS
TL;DR
Payload CMS is the right foundation for content-heavy SaaS products. It's a headless CMS and application framework in one — perfect for products where managing structured content (courses, documentation, articles, products) is a core feature. Not a SaaS boilerplate in the traditional sense; better described as an application platform. At free (MIT), the value is significant.
What Payload CMS Is
Payload 2.0+ is different from traditional CMS tools:
- App framework: Build custom applications with Payload's API
- Headless CMS: Structured content with auto-generated admin
- Authentication: Built-in auth with access control
- API-first: REST and GraphQL auto-generated
// payload.config.ts — define your data model
import { buildConfig } from 'payload/config';
export default buildConfig({
serverURL: process.env.SERVER_URL!,
admin: {
user: Users.slug,
meta: { titleSuffix: '— YourSaaS CMS' },
},
collections: [
Users, // Auth users
Courses, // Course content
Lessons, // Individual lessons
Media, // File uploads
Orders, // Purchase records
],
globals: [
SiteSettings, // Global config
],
});
Collections: The Core Concept
// collections/Courses.ts
import type { CollectionConfig } from 'payload/types';
export const Courses: CollectionConfig = {
slug: 'courses',
admin: {
useAsTitle: 'title',
},
access: {
read: () => true, // Public read
create: isAdmin, // Admin only create
update: isAdmin,
delete: isAdmin,
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'text', required: true, unique: true },
{ name: 'description', type: 'richText' },
{
name: 'price',
type: 'number',
required: true,
min: 0,
},
{
name: 'lessons',
type: 'relationship',
relationTo: 'lessons',
hasMany: true,
},
{
name: 'thumbnail',
type: 'upload',
relationTo: 'media',
},
{
name: 'status',
type: 'select',
options: ['draft', 'published'],
defaultValue: 'draft',
},
],
hooks: {
afterChange: [
async ({ doc }) => {
// Invalidate Next.js cache on content change
await revalidatePath(`/courses/${doc.slug}`);
},
],
},
};
This auto-generates:
- Admin UI for managing courses
- REST API at
/api/courses - GraphQL queries for courses
Access Control
// Payload's access control is powerful
const isAdmin = ({ req: { user } }) => user?.role === 'admin';
const isPurchased = async ({ req, id }) => {
if (!req.user) return false;
const order = await payload.find({
collection: 'orders',
where: {
and: [
{ purchaser: { equals: req.user.id } },
{ course: { equals: id } },
{ status: { equals: 'paid' } },
],
},
});
return order.totalDocs > 0;
};
export const Lessons: CollectionConfig = {
slug: 'lessons',
access: {
read: isPurchased, // Only show content to buyers
},
// ...
};
Fine-grained access control is built into the data model.
When Payload CMS Makes Sense
Best use cases:
- Online course platforms (lessons, modules, student access)
- Documentation sites with gated premium content
- SaaS where content management is a core workflow for the client
- Products with complex structured content (product catalogs, knowledge bases)
- White-label platforms where clients manage their own content
Less ideal for:
- Simple subscription SaaS without significant content management
- Real-time collaborative apps (Payload isn't built for it)
- Mobile-first products (more complex API integration)
Payload CMS + Next.js + Stripe Pattern
The common SaaS pattern with Payload:
// app/courses/[slug]/page.tsx — Next.js + Payload
async function CoursePage({ params }) {
const course = await payload.findOne({
collection: 'courses',
where: { slug: { equals: params.slug } },
});
const isPurchased = await checkPurchase(userId, course.id);
if (!isPurchased) {
return <PurchasePage course={course} />;
}
return <CourseContent course={course} />;
}
// After Stripe checkout — grant access
export async function POST(req: Request) {
const event = stripe.webhooks.constructEvent(/* ... */);
if (event.type === 'checkout.session.completed') {
const { courseId, userId } = event.data.object.metadata;
await payload.create({
collection: 'orders',
data: {
purchaser: userId,
course: courseId,
status: 'paid',
amount: event.data.object.amount_total,
},
});
}
}
Limitations
- Learning curve: Payload's config model is different from traditional SaaS patterns
- Not a complete SaaS starter: No billing UI, no marketing pages out of the box
- Deployment: Requires a server (no static export) — Node.js runtime
- MongoDB required (v1) or PostgreSQL (v2+) — slightly more setup
Who Should Use Payload CMS
Good fit:
- Content-heavy products (courses, documentation, media platforms)
- Products where clients manage their own content
- Teams who want a CMS and application framework in one
- Developers building white-label content platforms
Bad fit:
- Simple subscription SaaS
- Teams who want full boilerplate features out of the box
- Serverless-only environments
Final Verdict
Rating: 4/5 for its use case
Payload CMS is an excellent choice for content-driven products. It's not a traditional SaaS boilerplate, but for the right product type, it's far better than bolting a CMS onto a traditional boilerplate. The free, MIT license is exceptional value.
Find content-platform boilerplates on StarterPick.
Check out this boilerplate
View Payload CMS on StarterPick →