payloadcms-website-3-84-1

star 2

Payload CMS website template providing production-ready starter for content-driven websites, blogs, and portfolios with Next.js App Router, MongoDB, Lexical editor, SEO optimization, draft/live preview, and search. Use when building personal or enterprise-grade websites requiring publication workflows, layout builders, multi-page sites, or integrating Payload CMS with modern frontend technologies.

tangledgroup By tangledgroup schedule Updated 6/11/2026

name: payloadcms-website-3-84-1 description: Payload CMS website template providing production-ready starter for content-driven websites, blogs, and portfolios with Next.js App Router, MongoDB, Lexical editor, SEO optimization, draft/live preview, and search. Use when building personal or enterprise-grade websites requiring publication workflows, layout builders, multi-page sites, or integrating Payload CMS with modern frontend technologies.

Payload CMS Website Template 3.84.1

Overview

The Payload CMS Website Template is the official production-ready starter for building content-driven websites, blogs, and portfolios — from small personal sites to enterprise-grade platforms. It combines Payload 3.x's headless CMS with Next.js 16 App Router, providing a fully integrated backend, admin panel, and frontend in a single deployable application.

The template ships with five pre-configured collections (Pages, Posts, Media, Categories, Users), two globals (Header, Footer), a block-based layout builder, Lexical rich text editor with view override system, draft and live preview workflows, SEO plugin integration, full-text search, URL redirects, form builder with multipart upload support, scheduled publishing via jobs queue, and on-demand Next.js cache revalidation.

Key differentiators from the blank template:

  • Layout Builder — composable page sections using blocks (Hero, Content, Media, Call To Action, Archive)
  • Publication Workflow — draft/published states with versions, autosave, and scheduled publishing
  • Live Preview — real-time preview of drafts in the admin panel with SSR rendering
  • On-Demand Revalidation — automatic Next.js cache invalidation on content changes
  • SEO Plugin — meta title, description, image, and OG preview from the admin
  • Search Plugin — SSR-powered full-text search indexed from posts
  • Redirects Plugin — admin-managed URL redirects with proper HTTP status codes
  • Form Builder Plugin — configurable contact and feedback forms with multipart upload support
  • Nested Docs Plugin — hierarchical categories (e.g., "News > Technology")

New in 3.83/3.84:

  • Multipart uploads in form builder plugin for file attachments
  • Lexical view override system for custom node rendering in rich text
  • definePlugin helper with execution ordering and cross-plugin discovery
  • Profiling utilities for performance analysis
  • Drizzle uuidv7 support for globally sortable unique identifiers
  • Storage composite prefixes for simplified key handling
  • Custom collection views with client components

When to Use

  • Building a personal or enterprise-grade website, blog, or portfolio
  • Creating a content publishing platform with a fully featured publication workflow
  • Starting a new Payload project with pre-built collections, layout builder, and plugins
  • Implementing draft preview and live preview in a Next.js application
  • Setting up SEO-managed pages with admin-controlled meta data
  • Adding full-text search to a content-driven website
  • Migrating an existing site with URL redirect management
  • Building contact forms or feedback forms from the CMS admin

Core Concepts

Template Architecture

The template follows Payload's fullstack pattern — backend (Payload CMS) and frontend (Next.js) share a single instance. The src/app directory is split into two route groups:

  • (payload)/ — Admin panel and API routes (auto-generated by Payload)
  • (frontend)/ — Public-facing website pages built with Next.js App Router

Collections

Five collections form the data model:

  • Pages — Layout builder enabled, draft/published, SEO tab, slug-based routing at /{slug}. Home page uses slug home.
  • Posts — Rich text content with Lexical, hero image, related posts, categories, draft/published, SEO tab. Routed at /posts/{slug}.
  • Media — Upload-enabled collection with pre-configured image sizes (thumbnail, square, small, medium, large, xlarge, og), focal point support, folder organization, and caption via rich text.
  • Categories — Taxonomy for grouping posts. Supports nesting via the nested-docs plugin. Public read access.
  • Users — Auth-enabled collection controlling admin panel access. Name field only beyond email/password.

Globals

Two globals manage site-wide content:

  • Header — Navigation items (array of links, max 6 rows). Public read access.
  • Footer — Footer navigation items (same structure as header). Public read access.

Both globals have afterChange hooks that trigger on-demand revalidation so the frontend updates immediately.

Layout Builder

Pages use a blocks field for composable layouts. Available blocks:

  • Hero — Select group with type options (none, highImpact, mediumImpact, lowImpact), rich text content, link group, and optional media.
  • Content — Standard content block with columns and rich text.
  • MediaBlock — Renders media from the Media collection with caption support.
  • CallToAction — Promotional section with heading, rich text, and links.
  • Archive — Lists posts by collection or individual selection, filterable by category with configurable limit.
  • Form — Form builder block for embedding forms on pages.

Posts use a different content model — Lexical rich text with inline blocks (Banner, Code, MediaBlock) rather than the page-level layout builder.

Access Control Pattern

The template uses three access control functions:

  • anyone — Returns true (public access, used for Media and Categories read)
  • authenticated — Returns Boolean(user) (logged-in users only, used for create/update/delete)
  • authenticatedOrPublished — Returns true for logged-in users, otherwise filters by _status: { equals: 'published' } (used for Pages and Posts read)

Plugins

Five official plugins are configured in src/plugins/index.ts:

  1. redirectsPlugin — Manages URL redirects for pages and posts collections, with afterChange revalidation hook
  2. nestedDocsPlugin — Enables hierarchical nesting for categories, generates nested URLs from slug chains
  3. seoPlugin — Provides meta title/description/image fields with generate functions for automatic SEO data
  4. formBuilderPlugin — Creates form definitions and submissions, with payment disabled, Lexical editor for confirmation messages, and multipart upload support (new in 3.84)
  5. searchPlugin — Indexes posts for full-text search with beforeSync hook to populate categories and metadata

Project Structure

website-template/
├── src/
│   ├── app/
│   │   └── (frontend)/          # Public website
│   │       ├── [slug]/page.tsx  # Dynamic page routes
│   │       ├── posts/[slug]/    # Post routes
│   │       ├── search/          # Search results page
│   │       ├── next/preview/    # Draft preview endpoint
│   │       ├── (sitemaps)/      # XML sitemaps
│   │       ├── layout.tsx       # Root layout with Header/Footer/AdminBar
│   │       ├── page.tsx         # Home page (delegates to [slug]/page)
│   │       └── not-found.tsx    # 404 page
│   │   └── (payload)/           # Payload backend
│   │       ├── admin/           # Auto-generated admin panel
│   │       └── api/             # Auto-generated API routes
│   ├── collections/
│   │   ├── Pages/               # Pages collection + revalidate hooks
│   │   ├── Posts/               # Posts collection + revalidate hooks
│   │   ├── Users/               # Auth-enabled users
│   │   ├── Media.ts             # Upload collection with image sizes
│   │   └── Categories.ts        # Nested taxonomy
│   ├── globals/                 # (Header, Footer defined as modules)
│   ├── blocks/                  # Layout builder blocks
│   │   ├── ArchiveBlock/
│   │   ├── Banner/
│   │   ├── CallToAction/
│   │   ├── Code/
│   │   ├── Content/
│   │   ├── Form/
│   │   ├── MediaBlock/
│   │   ├── RelatedPosts/
│   │   └── RenderBlocks.tsx     # Block dispatcher component
│   ├── heros/                   # Hero components (high, medium, low impact)
│   ├── fields/                  # Reusable field definitions (link, linkGroup)
│   ├── access/                  # Access control functions
│   ├── hooks/                   # Shared hooks (revalidateRedirects, etc.)
│   ├── plugins/                 # Plugin configuration
│   ├── search/                  # Search plugin overrides and sync logic
│   ├── components/              # Shared React components
│   ├── providers/               # React context providers
│   ├── utilities/               # Helper functions (getURL, deepMerge, etc.)
│   ├── endpoints/               # Seed data endpoints
│   ├── payload.config.ts        # Central Payload configuration
│   └── payload-types.ts         # Auto-generated TypeScript types
├── public/media/                # Static file upload directory
├── next.config.ts               # Next.js config with withPayload wrapper
├── redirects.ts                 # Next.js redirect definitions (IE fallback)
├── tailwind.config.mjs          # Tailwind CSS configuration
├── tsconfig.json
├── Dockerfile                   # Multi-stage Docker build
└── docker-compose.yml           # Docker Compose with MongoDB

Installation / Setup

Quick Start

Use the create-payload-app CLI to scaffold the template:

pnpx create-payload-app my-project -t website
cd my-project
cp .env.example .env
pnpm install && pnpm dev

Open http://localhost:3000 and follow on-screen instructions to create the first admin user.

Environment Variables

Key variables from .env.example:

  • PAYLOAD_SECRET — Encryption secret for cookies and JWT
  • DATABASE_URL — MongoDB connection string
  • PREVIEW_SECRET — Secret for draft preview authentication
  • CRON_SECRET — Authorization bearer token for scheduled jobs
  • NEXT_PUBLIC_SERVER_URL — Public URL of the application
  • VERCEL_PROJECT_PRODUCTION_URL — Vercel deployment hostname (auto-detected)

Database Options

The template defaults to MongoDB via @payloadcms/db-mongodb. For Postgres on Vercel:

import { vercelPostgresAdapter } from '@payloadcms/db-vercel-postgres'

db: vercelPostgresAdapter({
  pool: {
    connectionString: process.env.POSTGRES_URL || '',
  },
}),

For Postgres with migrations, run pnpm payload migrate:create locally and pnpm payload migrate on deploy. Set push: false for production databases.

Seed Data

Click "seed database" from the admin panel to populate Pages, Posts, and Categories with sample content. This also creates a demo author account (demo-author@payloadcms.com / password). Seeding drops and recreates the database — use only on fresh projects.

Usage Examples

Payload Config

// src/payload.config.ts
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import sharp from 'sharp'
import path from 'path'
import { buildConfig } from 'payload'
import { fileURLToPath } from 'url'

import { Categories } from './collections/Categories'
import { Media } from './collections/Media'
import { Pages } from './collections/Pages'
import { Posts } from './collections/Posts'
import { Users } from './collections/Users'
import { Footer } from './Footer/config'
import { Header } from './Header/config'
import { plugins } from './plugins'
import { defaultLexical } from '@/fields/defaultLexical'
import { getServerSideURL } from './utilities/getURL'

const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

export default buildConfig({
  admin: {
    user: Users.slug,
    importMap: { baseDir: path.resolve(dirname) },
    livePreview: {
      breakpoints: [
        { label: 'Mobile', name: 'mobile', width: 375, height: 667 },
        { label: 'Tablet', name: 'tablet', width: 768, height: 1024 },
        { label: 'Desktop', name: 'desktop', width: 1440, height: 900 },
      ],
    },
  },
  collections: [Pages, Posts, Media, Categories, Users],
  cors: [getServerSideURL()].filter(Boolean),
  db: mongooseAdapter({ url: process.env.DATABASE_URL }),
  editor: defaultLexical,
  globals: [Header, Footer],
  plugins,
  secret: process.env.PAYLOAD_SECRET,
  sharp,
  typescript: { outputFile: path.resolve(dirname, 'payload-types.ts') },
  jobs: {
    access: {
      run: ({ req }) => {
        if (req.user) return true
        const secret = process.env.CRON_SECRET
        if (!secret) return false
        return req.headers.get('authorization') === `Bearer ${secret}`
      },
    },
    tasks: [],
  },
})

Pages Collection with Drafts and Revalidation

// src/collections/Pages/index.ts
export const Pages: CollectionConfig<'pages'> = {
  slug: 'pages',
  access: {
    create: authenticated,
    delete: authenticated,
    read: authenticatedOrPublished,
    update: authenticated,
  },
  admin: {
    useAsTitle: 'title',
    preview: (data, { req }) =>
      generatePreviewPath({ slug: data?.slug as string, collection: 'pages', req }),
    livePreview: {
      url: ({ data, req }) =>
        generatePreviewPath({ slug: data?.slug, collection: 'pages', req }),
    },
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    {
      type: 'tabs',
      tabs: [
        { label: 'Hero', fields: [hero] },
        {
          label: 'Content',
          fields: [{
            name: 'layout',
            type: 'blocks',
            blocks: [CallToAction, Content, MediaBlock, Archive, FormBlock],
            required: true,
          }],
        },
        {
          name: 'meta',
          label: 'SEO',
          fields: [
            OverviewField({ titlePath: 'meta.title', descriptionPath: 'meta.description', imagePath: 'meta.image' }),
            MetaTitleField({ hasGenerateFn: true }),
            MetaImageField({ relationTo: 'media' }),
            MetaDescriptionField({}),
            PreviewField({ hasGenerateFn: true, titlePath: 'meta.title', descriptionPath: 'meta.description' }),
          ],
        },
      ],
    },
    { name: 'publishedAt', type: 'date', admin: { position: 'sidebar' } },
    slugField(),
  ],
  hooks: {
    afterChange: [revalidatePage],
    beforeChange: [populatePublishedAt],
    afterDelete: [revalidateDelete],
  },
  versions: {
    drafts: {
      autosave: { interval: 100 },
      schedulePublish: true,
    },
    maxPerDoc: 50,
  },
}

On-Demand Revalidation Hook

// src/collections/Pages/hooks/revalidatePage.ts
import type { CollectionAfterChangeHook } from 'payload'
import { revalidatePath, revalidateTag } from 'next/cache'
import type { Page } from '../../../payload-types'

export const revalidatePage: CollectionAfterChangeHook<Page> = ({
  doc,
  previousDoc,
  req: { payload, context },
}) => {
  if (!context.disableRevalidate) {
    if (doc._status === 'published') {
      const path = doc.slug === 'home' ? '/' : `/${doc.slug}`
      payload.logger.info(`Revalidating page at path: ${path}`)
      revalidatePath(path)
      revalidateTag('pages-sitemap', 'max')
    }
    if (previousDoc?._status === 'published' && doc._status !== 'published') {
      const oldPath = previousDoc.slug === 'home' ? '/' : `/${previousDoc.slug}`
      revalidatePath(oldPath)
      revalidateTag('pages-sitemap', 'max')
    }
  }
  return doc
}

Frontend Page with Draft Mode and Local API

// src/app/(frontend)/[slug]/page.tsx
import { getPayload } from 'payload'
import configPromise from '@payload-config'
import { draftMode } from 'next/headers'
import { cache } from 'react'
import { RenderBlocks } from '@/blocks/RenderBlocks'
import { RenderHero } from '@/heros/RenderHero'
import { PayloadRedirects } from '@/components/PayloadRedirects'
import { LivePreviewListener } from '@/components/LivePreviewListener'

export default async function Page({ params: paramsPromise }: { params: Promise<{ slug?: string }> }) {
  const { isEnabled: draft } = await draftMode()
  const { slug = 'home' } = await paramsPromise
  const decodedSlug = decodeURIComponent(slug)

  const page = await queryPageBySlug({ slug: decodedSlug })

  if (!page) return <PayloadRedirects url={'/' + decodedSlug} />

  return (
    <article className="pt-16 pb-24">
      <PayloadRedirects disableNotFound url={'/' + decodedSlug} />
      {draft && <LivePreviewListener />}
      <RenderHero {...page.hero} />
      <RenderBlocks blocks={page.layout} />
    </article>
  )
}

const queryPageBySlug = cache(async ({ slug }: { slug: string }) => {
  const { isEnabled: draft } = await draftMode()
  const payload = await getPayload({ config: configPromise })
  const result = await payload.find({
    collection: 'pages',
    draft,
    limit: 1,
    pagination: false,
    overrideAccess: draft,
    where: { slug: { equals: slug } },
  })
  return result.docs?.[0] || null
})

Static Params Generation for ISR

export async function generateStaticParams() {
  const payload = await getPayload({ config: configPromise })
  const pages = await payload.find({
    collection: 'pages',
    draft: false,
    limit: 1000,
    overrideAccess: false,
    pagination: false,
    select: { slug: true },
  })
  return pages.docs
    ?.filter((doc) => doc.slug !== 'home')
    .map(({ slug }) => ({ slug }))
}

Advanced Topics

Collections and Data Model: Complete reference for Pages, Posts, Media, Categories, and Users collections including field definitions, access control, hooks, and versioning configuration → Collections and Data Model

Layout Builder and Blocks: Block-based page composition with Hero types, Content columns, Archive filtering, Form embedding, and the RenderBlocks dispatcher pattern → Layout Builder and Blocks

Plugins Configuration: Detailed setup for SEO, Search, Redirects, Form Builder with multipart uploads, and Nested Docs plugins including field overrides, sync hooks, and generate functions → Plugins Configuration

Frontend Architecture: Next.js App Router patterns including draft mode integration, React cache for queries, static params generation, metadata API, sitemaps, and the frontend layout structure → Frontend Architecture

Draft Preview and Live Preview: Draft preview URL generation, preview endpoint routing, live preview with SSR breakpoints, autosave configuration, and scheduled publishing → Draft Preview and Live Preview

Deployment and Production: Vercel deployment with Postgres adapter, self-hosting patterns, Docker multi-stage builds, cache strategies, cron configuration for scheduled jobs, and migration management → Deployment and Production

Install via CLI
npx skills add https://github.com/tangledgroup/tangled-skills --skill payloadcms-website-3-84-1
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
tangledgroup
tangledgroup Explore all skills →