Contentful charges per user. Strapi needs a separate server. Sanity has usage limits. Payload CMS lives INSIDE your Next.js app — same codebase, same deployment, same database. And it's 100% free and open source.
What Payload Gives You for Free
- Embedded in Next.js — not a separate service, it's in your app
- Admin panel — auto-generated from your config
- TypeScript-first — generated types from your collections
- Auth built-in — users, roles, permissions, API keys
- File uploads — local, S3, Cloudflare R2
- Rich text — Lexical editor (or Slate)
- Drafts & versions — content versioning built in
- Access control — field-level permissions
- PostgreSQL or MongoDB — you choose
Quick Start
npx create-payload-app@latest
Define Collections (Code-First Schema)
// collections/Posts.ts
import type { CollectionConfig } from 'payload';
export const Posts: CollectionConfig = {
slug: 'posts',
admin: { useAsTitle: 'title' },
access: {
read: () => true,
create: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => Boolean(user),
delete: ({ req: { user } }) => user?.role === 'admin',
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'text', unique: true },
{
name: 'content',
type: 'richText',
},
{
name: 'author',
type: 'relationship',
relationTo: 'users',
},
{
name: 'status',
type: 'select',
options: ['draft', 'published'],
defaultValue: 'draft',
},
{
name: 'featuredImage',
type: 'upload',
relationTo: 'media',
},
{
name: 'tags',
type: 'array',
fields: [{ name: 'tag', type: 'text' }],
},
],
};
Use In Your Next.js Pages
// app/blog/page.tsx
import { getPayload } from 'payload';
import config from '@payload-config';
export default async function BlogPage() {
const payload = await getPayload({ config });
const { docs: posts } = await payload.find({
collection: 'posts',
where: { status: { equals: 'published' } },
sort: '-createdAt',
limit: 10,
});
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
</article>
))}
</div>
);
}
No API calls. No fetch. Direct database access in your server components.
Payload vs Contentful vs Strapi vs Sanity
| Feature | Payload | Contentful | Strapi | Sanity |
|---|---|---|---|---|
| Price | Free (self-hosted) | $300+/mo | Free (self-hosted) | Usage-based |
| Deployment | Inside your app | Separate service | Separate server | Hosted |
| TypeScript | First-class | SDK only | Plugin | SDK only |
| Database | PostgreSQL/MongoDB | Hosted | SQLite/PostgreSQL | Hosted |
| Auth | Built-in | Separate | Built-in | Separate |
| Vendor lock-in | Zero | High | Low | Medium |
The Verdict
Payload is the CMS that lives inside your app. No separate service, no external API calls, no vendor lock-in. Code-first config, TypeScript types, and a beautiful admin panel — all in your Next.js codebase.
Need help building production web scrapers or data pipelines? I build custom solutions. Reach out: spinov001@gmail.com
Check out my awesome-web-scraping collection — 400+ tools for extracting web data.
Top comments (0)