Payload CMS auto-generates REST and GraphQL APIs from your TypeScript config — and it's fully open-source.
Define Your Schema
// payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
collections: [
{
slug: 'posts',
auth: false,
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'richText' },
{ name: 'status', type: 'select', options: ['draft', 'published'] },
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'tags', type: 'array', fields: [
{ name: 'tag', type: 'text' }
]},
{ name: 'featuredImage', type: 'upload', relationTo: 'media' }
],
hooks: {
beforeChange: [({ data }) => {
data.slug = data.title.toLowerCase().replace(/\s+/g, '-')
return data
}]
}
}
]
})
Auto-Generated REST API
# List posts
GET /api/posts?limit=10&where[status][equals]=published&sort=-createdAt
# Get single post
GET /api/posts/POST_ID
# Create post
POST /api/posts
{ "title": "New Post", "content": {...}, "status": "draft" }
# Update post
PATCH /api/posts/POST_ID
{ "status": "published" }
# Delete
DELETE /api/posts/POST_ID
Local API — Direct Database Access
// No HTTP overhead — direct database calls
import { getPayloadClient } from 'payload'
const payload = await getPayloadClient()
const posts = await payload.find({
collection: 'posts',
where: { status: { equals: 'published' } },
sort: '-createdAt',
limit: 10,
depth: 2 // Populate relationships 2 levels deep
})
const newPost = await payload.create({
collection: 'posts',
data: { title: 'Created via Local API', status: 'published' }
})
Access Control
{
slug: 'posts',
access: {
read: () => true, // Everyone can read
create: ({ req }) => req.user?.role === 'admin', // Only admins create
update: ({ req, id }) => {
if (req.user?.role === 'admin') return true
return { author: { equals: req.user?.id } } // Authors edit own posts
},
delete: ({ req }) => req.user?.role === 'admin'
}
}
Real-World Use Case
An agency was using Strapi but hit limits with complex relations and custom logic. They switched to Payload: TypeScript-native config, the Local API eliminated N+1 queries, and access control replaced 500 lines of middleware. Same features, half the code, full type safety.
Payload CMS is what happens when backend developers build a CMS.
Build Smarter Data Pipelines
Need to scrape websites, extract APIs, or automate data collection? Check out my ready-to-use scrapers on Apify — no coding required.
Custom scraping solution? Email me at spinov001@gmail.com — fast turnaround, fair prices.
Top comments (0)