Self-Host Payload CMS: Modern TypeScript Headless CMS & Application Framework

cover

What is Payload CMS?

Payload is a revolutionary TypeScript-based headless CMS and application framework that accelerates how developers build modern digital experiences. Unlike traditional CMS platforms, Payload provides everything you need in one place - content management, authentication, file storage, and APIs - without the complexity of microservices. This self-hosted alternative to Strapi, Contentful, and Sanity offers enterprise-grade features with complete data ownership and no vendor lock-in.

Key Features of Payload Platform

🚀 Developer-First Architecture

  • 100% TypeScript: Type-safe from database to API with full IntelliSense support
  • Code-First Configuration: Define your content model in code, not through UI clicks
  • Express.js Foundation: Built on familiar Node.js technologies you already know
  • React Admin Panel: Fully customizable admin UI with React components
  • GraphQL & REST APIs: Auto-generated, fully documented APIs from your schema

🎨 Powerful Admin Interface

  • Beautiful Admin UI: Modern, responsive interface that clients and editors love
  • Live Preview: Real-time content preview with your frontend application
  • Block-Based Editor: Flexible content blocks for rich page building
  • Localization Built-in: Multi-language content management out of the box
  • Media Management: Advanced file upload with automatic image optimization

🔐 Enterprise Features

  • Authentication System: Complete auth with users, roles, and permissions
  • Access Control: Fine-grained, field-level access control
  • Drafts & Versioning: Content versioning with draft/publish workflows
  • Webhooks: Real-time integrations with external systems
  • Search: Full-text search powered by your database

⚡ Performance & Scalability

  • Database Agnostic: Works with MongoDB and PostgreSQL
  • Automatic Migrations: Schema changes handled automatically
  • Query Optimization: Efficient queries with relationship population
  • Caching Strategy: Built-in caching for optimal performance
  • Horizontal Scaling: Deploy across multiple servers seamlessly

Why Choose Payload Over Commercial Alternatives?

Payload vs Strapi (Open Source)

FeaturePayloadStrapi
TypeScript Native✅ Full TypeScript⚠️ JavaScript with TS definitions
Admin Customization✅ React Components❌ Limited customization
Code-First Config✅ Yes❌ UI-based configuration
Field-Level Access✅ Built-in❌ Basic RBAC only
Block Editor✅ Native support❌ Requires plugins
Live Preview✅ Built-in❌ Limited support

Payload vs Contentful ($489+/month)

FeaturePayload (Self-Hosted)Contentful
Monthly CostFree & Open Source$489-2000+/month
Data Ownership✅ Complete Control❌ Vendor Lock-in
API Rate Limits✅ Unlimited❌ Rate Limited
Custom Fields✅ Unlimited❌ Plan Limitations
Environments✅ Unlimited❌ Limited by Plan
Storage✅ Your Infrastructure❌ Quota Limits

Payload vs Sanity ($99+/month)

  • Hosting Flexibility: Self-host anywhere vs cloud-only deployment
  • Database Choice: MongoDB or PostgreSQL vs proprietary database
  • Query Language: GraphQL/REST vs GROQ learning curve
  • Pricing Model: Free forever vs usage-based pricing
  • Data Portability: Standard database vs proprietary format

Quick Deployment Options

Perfect for production deployments with complete control.

version: '3.8'
services:
  payload:
    image: node:18-alpine
    working_dir: /app
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URI=mongodb://mongo:27017/payload
      - PAYLOAD_SECRET=your-secret-key-here
      - NODE_ENV=production
    command: npx create-payload-app
    depends_on:
      - mongo
    volumes:
      - ./media:/app/media
      - ./src:/app/src

  mongo:
    image: mongo:6
    ports:
      - "27017:27017"
    volumes:
      - mongo_data:/data/db
    environment:
      - MONGO_INITDB_DATABASE=payload

volumes:
  mongo_data:

Option 2: Create Payload App (Quick Start)

Fastest way to get started with Payload CMS.

# Create new Payload project
npx create-payload-app@latest my-project

# Choose your options:
# - Database: MongoDB or PostgreSQL
# - Template: Blank, Blog, E-commerce, or Custom
# - TypeScript: Yes (recommended)

cd my-project
npm run dev

# Access at http://localhost:3000/admin

Option 3: Manual Installation

For adding Payload to existing Express applications.

# Install Payload and dependencies
npm install payload express
npm install -D typescript @types/express

# Create payload.config.ts
cat > payload.config.ts << 'EOF'
import { buildConfig } from 'payload/config';
import Users from './collections/Users';
import Media from './collections/Media';

export default buildConfig({
  serverURL: 'http://localhost:3000',
  admin: {
    user: Users.slug,
  },
  collections: [
    Users,
    Media,
    // Add your collections here
  ],
  typescript: {
    outputFile: './types/payload-types.ts',
  },
});
EOF

# Initialize and start
npm run dev

Getting Started with Payload CMS

Initial Setup Process

  1. Install Payload: Use create-payload-app or add to existing project
  2. Configure Database: Set up MongoDB or PostgreSQL connection
  3. Create First User: Access /admin to create administrator account
  4. Define Collections: Create your content models in TypeScript
  5. Customize Admin: Extend the admin UI with React components

Collection Configuration Example

// collections/Articles.ts
import { CollectionConfig } from 'payload/types';

const Articles: CollectionConfig = {
  slug: 'articles',
  admin: {
    useAsTitle: 'title',
    defaultColumns: ['title', 'status', 'createdAt'],
  },
  access: {
    read: () => true,
    create: ({ req: { user } }) => Boolean(user),
    update: ({ req: { user } }) => Boolean(user?.roles?.includes('editor')),
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
      localized: true,
    },
    {
      name: 'content',
      type: 'richText',
      required: true,
    },
    {
      name: 'author',
      type: 'relationship',
      relationTo: 'users',
      required: true,
    },
    {
      name: 'status',
      type: 'select',
      options: ['draft', 'published'],
      defaultValue: 'draft',
    },
    {
      name: 'publishedAt',
      type: 'date',
      admin: {
        position: 'sidebar',
      },
    },
  ],
  hooks: {
    beforeChange: [
      ({ data, req }) => {
        // Auto-set published date
        if (data.status === 'published' && !data.publishedAt) {
          data.publishedAt = new Date();
        }
        return data;
      },
    ],
  },
};

export default Articles;

API Usage Examples

// REST API Examples
// GET all articles
fetch('http://localhost:3000/api/articles')

// GET single article
fetch('http://localhost:3000/api/articles/123')

// CREATE article (authenticated)
fetch('http://localhost:3000/api/articles', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN'
  },
  body: JSON.stringify({
    title: 'New Article',
    content: 'Article content...',
    author: 'user-id'
  })
})

// GraphQL Query Example
const query = `
  query GetArticles {
    Articles(limit: 10, where: { status: { equals: "published" } }) {
      docs {
        id
        title
        content
        author {
          name
          email
        }
        publishedAt
      }
      totalDocs
    }
  }
`;

Content Management System

  • Marketing Websites: Build dynamic marketing sites with page builder
  • Multi-site Management: Manage multiple websites from one CMS
  • Blog Platform: Full-featured blogging with categories and authors
  • Documentation Sites: Technical documentation with versioning

E-commerce Platform

  • Product Catalog: Complex product management with variants
  • Order Management: Complete order processing workflow
  • Customer Portal: User accounts with order history
  • Inventory Tracking: Stock management and notifications

Application Backend

  • SaaS Applications: Complete backend for software products
  • Mobile App APIs: Backend for React Native/Flutter apps
  • Internal Tools: Admin panels and dashboards
  • Workflow Automation: Business process management

Digital Asset Management

  • Media Library: Centralized media storage and distribution
  • Image Optimization: Automatic resizing and format conversion
  • Video Management: Stream video content with thumbnails
  • Document Repository: Secure document storage and sharing

Advanced Features & Customization

Custom React Components

// Custom field component
import React from 'react';
import { useField } from 'payload/components/forms';

const ColorPicker: React.FC = () => {
  const { value, setValue } = useField();
  
  return (
    <input
      type="color"
      value={value || '#000000'}
      onChange={(e) => setValue(e.target.value)}
    />
  );
};

// Register in field config
{
  name: 'color',
  type: 'text',
  admin: {
    components: {
      Field: ColorPicker,
    },
  },
}

Authentication & Access Control

// Advanced access control
access: {
  read: ({ req: { user } }) => {
    if (user?.roles?.includes('admin')) return true;
    return {
      author: {
        equals: user?.id,
      },
    };
  },
  update: ({ req: { user }, id }) => {
    // Custom logic for update permissions
    return checkUserPermission(user, id);
  },
}

Hooks & Middleware

// Collection hooks
hooks: {
  beforeChange: [
    async ({ data, req, operation }) => {
      if (operation === 'create') {
        // Send notification
        await sendEmail({
          to: 'admin@example.com',
          subject: 'New content created',
          body: `New ${data.title} created`,
        });
      }
      return data;
    },
  ],
  afterRead: [
    async ({ doc, req }) => {
      // Enhance document with computed fields
      doc.readingTime = calculateReadingTime(doc.content);
      return doc;
    },
  ],
}

Payload CMS Community & Ecosystem

  • GitHub Stars: 20,000+ stars with rapid growth
  • Discord Community: Active community with 5,000+ developers
  • Plugin Ecosystem: Growing library of community plugins
  • Documentation: Comprehensive docs with examples and tutorials
  • Enterprise Support: Commercial support and consulting available
  • Regular Updates: Monthly releases with new features

Migration Guide

From WordPress

  1. Export Content: Use WordPress export tools or direct database access
  2. Create Collections: Map WordPress post types to Payload collections
  3. Import Script: Write migration script using Payload's Local API
  4. Media Migration: Transfer wp-content/uploads to Payload media
  5. User Migration: Import WordPress users with role mapping

From Strapi

  1. Schema Mapping: Convert Strapi content types to Payload collections
  2. API Migration: Update frontend to use Payload's REST/GraphQL APIs
  3. Plugin Replacement: Find Payload equivalents for Strapi plugins
  4. Database Migration: Export from Strapi and import to Payload
  5. Custom Code: Port any custom Strapi code to Payload hooks

Transform your content management with Payload CMS - the modern, TypeScript-native CMS that gives you complete control without the complexity of microservices or expensive SaaS subscriptions.