Payload
Payload powers the two CMS control planes. The CMS apps are product surfaces, not generic admin dashboards.
What It Owns
Section titled “What It Owns”apps/cms-customeris the customer/deployment operator control plane.apps/cms-leverageis the Leverage-owned internal product improvement and operations control plane.@repo/payload-cms-authand@repo/payload-emailhold shared CMS integration helpers.- Payload native auth owns CMS operator accounts. Better Auth remains the web-user authority.
Architecture Decision
Section titled “Architecture Decision”Decision: use two separate Payload apps instead of one shared CMS app.
The split keeps customer-local settings, customer-visible review surfaces, Leverage-owned product improvement workflows, databases, service credentials, and deployment boundaries separate. Customer-cluster release paths must never include Leverage-owned CMS credentials or internal-only configuration.
How To Upgrade
Section titled “How To Upgrade”-
Read Payload release notes, the database adapter docs, and migration notes for the target version.
-
Compare against a fresh Payload blank MongoDB template before choosing CMS companion package versions. Use a gitignored temp directory, skip dependency installation and agent setup, then inspect only the generated
package.json:Terminal window mkdir -p tmp/payload-template-comparecd tmp/payload-template-comparebunx create-payload-app@latest -n payload-template-blank -t blank --use-bun --no-deps --no-agentSelect MongoDB when prompted, because both CMS apps use
@payloadcms/db-mongodb. Keep Payload-owned packages on the template’s package line even when the registry has a newer patch for a companion package such as Next, React, oreslint-config-next. Do not downgrade an already-newer configured package just to match the template unless the human explicitly approves that downgrade. -
Keep
payloadand all@payloadcms/*packages aligned across both CMS apps:Terminal window # from apps/cms-customerbun add --exact payload@$PAYLOAD_VERSION @payloadcms/db-mongodb@$PAYLOAD_VERSION @payloadcms/next@$PAYLOAD_VERSION @payloadcms/richtext-lexical@$PAYLOAD_VERSION @payloadcms/ui@$PAYLOAD_VERSION# from apps/cms-leveragebun add --exact payload@$PAYLOAD_VERSION @payloadcms/db-mongodb@$PAYLOAD_VERSION @payloadcms/next@$PAYLOAD_VERSION @payloadcms/richtext-lexical@$PAYLOAD_VERSION @payloadcms/ui@$PAYLOAD_VERSION -
Keep
@repo/payload-cms-authand@repo/payload-emailpeer/dependency ranges aligned to the selected Payload line. -
Regenerate Payload artifacts where relevant:
Terminal window bun run --cwd apps/cms-customer generate:importmapbun run --cwd apps/cms-customer generate:typesbun run --cwd apps/cms-leverage generate:importmapbun run --cwd apps/cms-leverage generate:types -
For data-shape changes, use Payload migrations only when there is existing data to transform. With MongoDB, Payload’s docs say migrations may be needed only once in a while, or never, unless existing documents need to move from one shape to another.
-
Run both CMS typechecks and integration lanes.
Current Limits
Section titled “Current Limits”- Do not collapse
cms-customerandcms-leverageinto one app or one account store. - Do not add Leverage-owned credentials, services, or internal CMS config to customer-cluster manifests.
- Do not add historical single-CMS aliases such as
CMS_BASE_URL.
Canonical Sources
Section titled “Canonical Sources”apps/cms-customer/src/payload.config.tsapps/cms-leverage/src/payload.config.tsapps/cms-customer/package.jsonapps/cms-leverage/package.jsonpackages/payload-cms-auth/packages/payload-email/docs/features/cms-control-plane-split/spec.mddocs/features/authentication/spec.md