Help Center
Environment Variables
Operator reference for every Seedly Sites environment variable - what each setting does, where it goes, and which ones are required.
Every operator-facing setting a live instance cares about, grouped by area. Three kinds of value:
- generated - the platform's own secrets, produced by
npx pnpm run gen:secrets - provider - a key you get from a third party (Railway, Cloudflare, Stripe, and so on)
- config - a plain value you choose
Where they go: app-owned secrets and most config go on the Railway cms service (saving redeploys it). A few also go on the pagebuilder service or as GitHub Actions secrets for the deploy pipeline. In the local sandbox most of these are unset and the platform falls back to safe defaults.
The authoritative check is the doctor: npx pnpm run setup:check -- --target=prod names exactly what is missing for a live instance. This page explains what each value is for - never the values themselves. Keep every secret in a password manager (Backups) and never commit one to Git.
Core / Auth#
| Name | Kind | Required | Purpose |
|---|---|---|---|
PAYLOAD_SECRET | generated | yes | Signs sessions and tokens. Distinct per environment; rotating it signs everyone out |
SUPER_ADMIN_EMAIL | config | yes | The locked super-admin identity. Set your own; the doctor flags the vendor default |
CRON_SECRET | generated | yes (prod) | Authenticates scheduled-job routes (backups, scheduled publish, retention) |
SEED_SECRET | generated | no | Gates the one-time bootstrap endpoint |
DEPLOY_STATUS_SECRET | generated | no | Authenticates deploy-status callbacks from the tenant deploy workflow |
PAYLOAD_EMAIL / PAYLOAD_PASSWORD | config / generated | no | Service-account login the build and render tooling use to reach the CMS API |
INSTANCE_BRAND_NAME | config | no | White-label name shown in admin chrome and emails |
SUPPORT_EMAIL | config | no | Support contact surfaced to clients |
Database#
| Name | Kind | Required | Purpose |
|---|---|---|---|
PAYLOAD_ADAPTER | config | yes (prod) | Unset = the local sandbox file database; set for the Postgres adapter in production |
DATABASE_URL | provider | yes (prod) | The Railway Postgres connection string |
Cloudflare (Media + Hosting)#
| Name | Kind | Required | Purpose |
|---|---|---|---|
R2_ENDPOINT | provider | yes (prod) | The R2 storage endpoint for durable media. Without the R2 keys, storage falls back to ephemeral local disk |
R2_ACCESS_KEY_ID | provider | yes (prod) | R2 access key id |
R2_SECRET_ACCESS_KEY | provider | yes (prod) | R2 secret access key |
R2_BUCKET_NAME | config | no | Bucket name (has a sensible default) |
R2_PUBLIC_URL | config | yes (build) | Public base URL media is served from; applied when a site is built |
CF_API_TOKEN | provider | yes (prod) | Token the platform uses to auto-create per-site Pages projects. Also a GitHub Actions secret |
CF_ACCOUNT_ID | config | yes (prod) | Your Cloudflare account id |
GitHub Deploy#
| Name | Kind | Required | Purpose |
|---|---|---|---|
GITHUB_DEPLOY_TOKEN | provider | yes (prod) | A GitHub token (repo and workflow scope) that dispatches the tenant deploy workflow |
GITHUB_DEPLOY_REPO | config | yes (prod) | The repo the deploy workflow runs in. Set your OWN repo; the doctor flags the vendor default |
AI#
| Name | Kind | Required | Purpose |
|---|---|---|---|
ANTHROPIC_API_KEY | provider | yes | Claude API key for brand-DNA generation, port revision, and visual QA |
SEEDLY_DNA_MODEL / SEEDLY_QA_MODEL / SEEDLY_REVISE_MODEL | config | no | Override the model each AI flow uses |
Email#
| Name | Kind | Required | Purpose |
|---|---|---|---|
SENDGRID_API_KEY | provider | yes (prod) | Transport for auth and notification email. Unset = those emails are logged, not sent |
EMAIL_FROM_ADDRESS | config | yes (prod) | Default From address; must be a verified sender at your email provider |
Studio / Render Wiring#
| Name | Kind | Required | Purpose |
|---|---|---|---|
STUDIO_INTERNAL_URL | config | yes (prod) | The studio's internal URL; the CMS proxies the builder to it so the builder is same-origin in production |
CMS_BASE_URL | config | no | Canonical CMS origin for absolute links |
RENDER_BASE_URL | config | no | CMS-to-render base for preview links |
PAYLOAD_API_URL | config | no | The CMS API origin the render/studio build talks to |
PUBLIC_CMS_URL | config | no | The CMS origin baked into the studio build |
STUDIO_ORIGIN | config | no | An extra allowed origin for a dev-direct studio |
Billing (Optional)#
All optional: leave unset and billing is simply inert. See Billing.
| Name | Kind | Purpose |
|---|---|---|
STRIPE_SECRET_KEY | provider | Your Stripe API key |
STRIPE_WEBHOOK_SECRET | provider | Verifies Stripe webhook signatures |
STRIPE_PRICE_ID | config | The subscription price the Subscribe button checks out |
BILLING_DEFAULT_ENFORCEMENT | config | Instance default when a lapsed tenant's enforcement is set to "default": edit lock, suspend, or none |
Optional Integrations (Fail Soft When Unset)#
| Name | Purpose |
|---|---|
GOOGLE_PLACES_API_KEY | Places lookup for location capture |
GOOGLE_MAPS_EMBED_API_KEY | Maps embed for the location card |
INDEXNOW_KEY | IndexNow key; unset = the search-engine ping on deploy is skipped |
SENTRY_DSN / NEXT_PUBLIC_SENTRY_DSN | Server and client error monitoring |
NEXT_PUBLIC_ADMIN_LOGO_URL | White-label logo on the admin/login screen |
NEXT_PUBLIC_ENABLE_AB_TESTS | Enables the experimental A/B tests feature |
SEEDLY_BACKUP_DIR | Backup output directory |
The intake (generate-from-brand-DNA) flow has additional keys of its own; they are intentionally not documented here yet.
