CMS

Shipkit uses Payload CMS v3 as its primary content management system. The admin panel lives at /cms and stores data in the same PostgreSQL database as the app (in a separate schema).

Setup

Payload is auto-enabled when DATABASE_URL is set. Disable it explicitly with DISABLE_PAYLOAD=true.

DATABASE_URL=postgres://user:pass@host:5432/db
PAYLOAD_SECRET=your-secret-key   # Or use APP_SECRET as fallback

On first run, Payload auto-seeds default content (pages, settings). Control this with:

  • PAYLOAD_AUTO_SEED=false to disable auto-seeding
  • PAYLOAD_SEED_FORCE=true to force a reseed

Admin Panel

Access at /cms. Also reachable from the admin dashboard at /admin/cms, which shows CMS status and a manual seed button.

The admin panel provides:

  • Content editing for all collections
  • Media management (uploads)
  • User management (Payload-specific users)
  • Live preview for pages

Collections

Pages

Block-based page composition. Each page has a title, slug, SEO metadata, and a layout field containing an array of blocks:

  • Hero - Hero section with title, subtitle, CTA
  • Content - Rich text content (Lexical editor)
  • Features - Feature list (references the Features collection)
  • Testimonials - Testimonial list (references the Testimonials collection)

Pages are accessible at /{slug}. Preview URL: /preview/pages/{slug}.

Media

File uploads with alt text. Supports S3 and Vercel Blob storage backends (see Storage). Public read access by default.

Users

Payload admin authentication. Separate from the app's NextAuth users, but synced: when a user signs up with credentials, they're created in both systems.

FAQs

Question/answer pairs with categories (General, Technical, Pricing, Support) and display ordering.

Features

Product features with name, description, category, plan association (Bones/Brains), badge (New/Popular/Pro), icon (Lucide icon name), and ordering.

Testimonials

User testimonials with name, role, company, text, avatar, and verified/featured flags.

RBAC

Role and permission definitions. Stores roles with associated permissions, scoped to resources (team, project, user, api-key, billing, settings) and actions (CRUD + manage).

Vercel Deployments

Read-only tracking of deployments initiated via the dashboard. Stores team/project/deployment IDs and URLs.

Settings (Global)

Site-wide configuration: site title, description, and seeding status tracking.

Unified Routing

Shipkit routes dynamic pages through both Payload and Builder.io:

  1. If Payload is enabled, it checks for a matching page by slug
  2. If not found and Builder.io is enabled, it checks Builder.io
  3. If neither has the page, returns 404

This happens in the catch-all route at src/app/(payload)/[...slug]/page.tsx.

Storage Backends

Media uploads can use:

BackendEnv VarsPlugin
S3AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BUCKET_NAME@payloadcms/storage-s3
Vercel BlobVERCEL_BLOB_READ_WRITE_TOKEN@payloadcms/storage-vercel-blob
LocalNoneDefault filesystem

Key Files

FilePurpose
src/payload.config.tsMain Payload configuration
src/lib/payload/collections/Collection definitions (Pages, Media, Users, FAQs, Features, Testimonials, RBAC, VercelDeployments)
src/lib/payload/blocks/Page block definitions (hero, content, features, testimonials)
src/lib/payload/seed/Seed data
src/app/(app)/(admin)/admin/cms/page.tsxAdmin CMS status page