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=falseto disable auto-seedingPAYLOAD_SEED_FORCE=trueto 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:
- If Payload is enabled, it checks for a matching page by slug
- If not found and Builder.io is enabled, it checks Builder.io
- 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:
| Backend | Env Vars | Plugin |
|---|---|---|
| S3 | AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BUCKET_NAME | @payloadcms/storage-s3 |
| Vercel Blob | VERCEL_BLOB_READ_WRITE_TOKEN | @payloadcms/storage-vercel-blob |
| Local | None | Default filesystem |
Key Files
| File | Purpose |
|---|---|
src/payload.config.ts | Main 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.tsx | Admin CMS status page |