payload-stack

Skip the SaaS plumbing: sign-in, teams, subscriptions and a shadcn dashboard on Payload + Next.js.

payload-stack screenshot
1 / 1
payload-stack screenshot

Overview

Summary generated from the README

Sets up a SaaS application on Payload CMS and Next.js with Better Auth for sign-in, organizations bridged into the multi-tenant plugin, and Stripe subscriptions. It includes a shadcn/ui dashboard, marketing pages and Payload admin as back office. Product settings live in one validated config file. Requires PostgreSQL and Stripe keys for billing, and it is scaffolded with a CLI.

Features

  • Better Auth login with email and password, magic link, passkeys, TOTP two-factor and social sign-in
  • Organizations with invitations, roles and switcher, enforced through the multi-tenant plugin
  • Stripe subscriptions per user or organization with seats, trials, customer portal and webhooks
  • Tailwind v4 and shadcn/ui dashboard shell with auth, settings and billing screens
  • React Email templates sent via Resend in production
  • Optional cookie consent plugin and configurable storage adapters for uploads

Good for

  • Launching a multi-tenant SaaS product with subscription billing
  • Building B2B apps where teams share organizations and seats
  • Starting a dashboard product that uses Payload admin as the back office

From the author

Payload Stack: a SaaS boilerplate on Payload CMS, Next.js, Better Auth, organizations, Stripe and shadcn/ui.

Get started

npx giget@latest gh:mpresecan/payload-solutions/templates/payload-stack my-app

README

Payload Stack

A SaaS boilerplate on Payload CMS and Next.js. Better Auth, organizations, Stripe subscriptions, a shadcn/ui dashboard and Payload's admin as your back office, wired together and driven by one config file.

Documentation: https://payload.solutions/docs/payload-stack

npx create-payload-stack@latest

What you get

AreaImplementation
AuthenticationBetter Auth through payload-auth: email + password, magic link, passkeys, TOTP two-factor, social sign-in, impersonation. One session for the app and the Payload admin.
OrganizationsBetter Auth organization plugin as the source of truth, bridged into @payloadcms/plugin-multi-tenant so every tenant-scoped collection is enforced in the API and the admin. Invitations, roles, switcher.
Billing@better-auth/stripe: plans from config, per user or per organization, seats, trials, customer portal, webhooks.
UITailwind v4, shadcn/ui (radix-nova), Better Auth UI for auth screens, account and security settings, organization management and billing. Dashboard shell from shadcn sidebar-08.
AdminPayload's admin at /admin for users, organizations, subscriptions, content and support, with a tenant selector.
EmailReact Email templates sent through Payload's email adapter (Resend in production, console in development).
ContentLegal pages as a Payload collection (seeded), rich text with Lexical, media uploads.
ConsentWith --consent, Cookie Consent: cookie banner and Google Consent Mode defaults, consent records, a processor register, generated cookie and sub-processor tables inside the legal pages, and a CLI that audits them against the project.
StorageUploads on local disk by default; the CLI wires Vercel Blob, S3 (and S3-compatible), Cloudflare R2, Azure Blob, Google Cloud Storage or Uploadthing into payload.config.ts, switched on by environment variables.
Configsrc/stack.config.ts validated with zod; src/lib/env.ts validates environment variables at boot.

Getting started

cp .env.example .env          # set DATABASE_URL, PAYLOAD_SECRET, NEXT_PUBLIC_APP_URL
docker compose up -d          # optional: local PostgreSQL + Mailpit
pnpm install
pnpm dev

Open http://localhost:3000/admin. The first visit creates your admin account. Then sign up as a regular user at http://localhost:3000/auth/sign-up to see onboarding, organizations and the dashboard.

Configure your product

Everything product-specific lives in src/stack.config.ts:

export default defineStack({
  name: 'Ridgeline',
  url: process.env.NEXT_PUBLIC_APP_URL,
  auth: { methods: ['email-password', 'magic-link', 'passkey'], social: ['google'], twoFactor: true },
  organizations: { enabled: true, allowUserToCreate: true },
  billing: { provider: 'stripe', attachedTo: 'organization', plans: [/* ... */] },
  legal: { company: 'Ridgeline Software Ltd', jurisdiction: 'Ireland' },
})

Turn organizations or billing off and the related UI, plugins and collections disappear. Add a social provider and the sign-in buttons, server plugin and env validation follow.

Stripe

  1. Create products and prices in Stripe, put the price ids in .env (NEXT_PUBLIC_STRIPE_PRICE_*).
  2. Set STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.
  3. Locally: stripe listen --forward-to localhost:3000/api/auth/stripe/webhook.

Checkout, the customer portal, cancel and restore are handled by Better Auth's Stripe plugin and Better Auth UI's billing views (/dashboard/organization/billing or /dashboard/settings/billing).

Scripts

CommandPurpose
pnpm devNext.js + Payload in development (schema pushed automatically)
pnpm build / pnpm startProduction build and server
pnpm generate:typesRegenerate src/payload-types.ts after changing collections
pnpm generate:importmapRegenerate the admin import map after adding plugins or admin components
pnpm db:migrate:create / pnpm db:migratePayload migrations for production databases
pnpm email:devPreview email templates at http://localhost:3001
pnpm test:int / pnpm test:e2eVitest integration tests, Playwright end-to-end tests (pnpm exec playwright install chromium once; set PLAYWRIGHT_CHROMIUM_PATH to reuse an existing Chromium)
pnpm lint / pnpm typecheckESLint and TypeScript

Project layout

src/
  stack.config.ts          product config
  payload.config.ts        Payload: collections, plugins, db, media storage, email
  collections/             Users, Organizations, Projects (example), Media, LegalPages
  consent/                 legal pages, seeding and the consent layer (with or without the plugin)
  access/                  shared access-control helpers
  tenancy/                 Better Auth memberships -> users.tenants bridge
  lib/                     stack schema, env, auth options/client/session, tenancy helpers, paths
  emails/                  transactional email senders
  components/
    ui/                    shadcn/ui
    auth/                  Better Auth UI (auth, settings, organization, billing, emails)
    marketing/             header, footer, pricing table, logo
    dashboard/             sidebar, navigation, header
  app/
    (frontend)/(marketing) home, pricing, legal/[slug]
    (frontend)/auth        auth/[path]
    (frontend)/(app)       onboarding, dashboard/**
    (frontend)/api/auth    Better Auth handler (and Stripe webhook)
    (payload)/             Payload admin and REST/GraphQL

Deploying

Any Node host or Vercel. Set the environment variables from .env.example, use a managed PostgreSQL (or the database you chose when scaffolding), point uploads at a storage adapter (local disk does not survive a redeploy on Vercel), and run pnpm db:migrate as part of your deploy instead of relying on schema push.

License

MIT. Payload Stack is a payload.solutions project. Payload, the Payload design, and related marks, designs, and logos are trademarks or registered trademarks of Payload CMS, Inc. in the U.S. and other countries.; Payload Solutions is not affiliated with or endorsed by Payload CMS, Inc.

More SaaS & dashboards templates

chapteros screenshot

chapteros

Self-hostable member portal for networking organisations with directory, referrals, events and presentations

0
v3
Next.js
Updated 1 months ago
payload-eve-chat screenshot

payload-eve-chat

AI chat agent inside the Payload admin, built on Vercel Eve with MCP tools for Posts and Tasks

15
v4
Next.js
Updated 4 days ago
refine-project screenshot

refine-project

Payload CMS 3 and Next.js 15 starter with a Refine and Ant Design admin dashboard, in English and Arabic

3
v3
Next.js
Updated 8 months ago