Royal Glow internal docs · now fully interactive — Steps, API tables, file trees & live status
Royal Glow Docs

Environment Variables

All 55 environment variables for the Royal Glow platform — what they do, where they go, and how they're validated.

Environment Variables

Royal Glow runs a monorepo with three Next.js apps (apps/web, apps/admin, apps/cms) plus the apps/invoicing PDF render service, deployed across Cloudflare Workers (rgss-web, rgss-admin — via the OpenNext adapter @opennextjs/cloudflare), Render (rgss-cms), and Cloud Run (apps/invoicing), and relies on ~15 external services.

Environment variables are validated at build time using @t3-oss/env-nextjs + Zod. If any required variable is missing or malformed, the build fails immediately. Never use process.env directly — always import from apps/web/src/env.ts.

Guarded-no-op pattern. Optional integrations (Redis, R2, Resend, Brevo, web-push, Ably, Slack, QStash heartbeats) degrade gracefully. When their keys are absent the related call becomes a no-op + log instead of throwing: the health probe reports skip rather than fail, the Ably token route returns 503 so the client falls back to polling, and background jobs still complete and return 200. This is why the app builds and runs with an incomplete .env — only the truly required core (database, auth) is hard-validated.

Quick Start

Copy templates

cp apps/web/.env.example apps/web/.env.local
cp apps/admin/.env.example apps/admin/.env.local
cp apps/cms/.env.example apps/cms/.env.local

Fill in values

Populate each .env.local with values from your service dashboards.

Generate VAPID keys (one-time only)

bunx web-push generate-vapid-keys

Validate

The build fails fast if anything required is missing or malformed.

cd apps/web && bun run build

File Structure

.env.example — root template (committed)
.env.local — local dev secrets, NEVER commit
.env.example — web-specific vars (committed)
.env.local — local overrides (gitignored)
.env.example — admin-specific vars (committed)
.env.example — cms-specific vars (committed)

Complete Variable Reference

Database (Neon)

Prop

Type

Per-environment branches: Use GitHub Environments so DATABASE_URL points to the correct Neon branch per environment (prod / pprd / test / dev).

Auth — Better Auth

Prop

Type

Email — Transactional (Resend)

Prop

Type

Email — Marketing (Brevo)

Prop

Type

Realtime — Ably

Prop

Type

File Storage — Cloudflare R2

Prop

Type

Cache — Upstash Redis

Prop

Type

Queue — Upstash QStash

Prop

Type

Web Push — VAPID Keys

Prop

Type

Generate once: bunx web-push generate-vapid-keys. These never change unless you intentionally rotate (which invalidates all existing push subscriptions).

Cloudflare — KV + CI/CD

Prop

Type

Observability — Sentry

Prop

Type

Observability — BetterStack

Prop

Type

Analytics — PostHog & Clarity

Prop

Type

Ads & Tracking — Meta

Prop

Type

Reporting

Prop

Type

CRM — AiSensy

Prop

Type

CMS — Payload

Prop

Type

App Configuration

Prop

Type

NODE_ENV vs APP_ENV: NODE_ENV is always development or production (Next.js convention). APP_ENV distinguishes between our 4 deployment environments: dev, test, pprd, prod. Use APP_ENV for environment-specific logic.

Variable Count Summary

CategoryCount
Database2
Auth4
Email (transactional + marketing)3
Realtime (Ably)2
File Storage (R2)5
Cache (Redis)2
Queue (QStash)3
Web Push (VAPID)3
Cloudflare KV + CI/CD3
Sentry4
BetterStack9
Analytics3
Meta Pixel + CAPI4
Reporting2
AiSensy2
Payload1
App Config3
Total55

Platform Injection

PlatformWhere to setApplied to
Cloudflare Workerswrangler secret / Workers & Pages → Settings → Variablesapps/web + apps/admin (edge)
RenderService → Environment tabapps/cms (Payload CMS)
Cloud RunService → Variables & Secretsapps/invoicing (PDF render)

All platforms inject vars at runtime — no .env file is needed or present in production.

GitHub Secrets

Set under Repository Settings → Secrets and variables → Actions:

DATABASE_URL_DEV / TEST / PPRD / PROD
DATABASE_URL_UNPOOLED_DEV / TEST / PPRD / PROD
BETTER_AUTH_SECRET
GOOGLE_OAUTH_CLIENT_ID / SECRET
... (all other secrets)

Reference in GitHub Actions:

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL_PROD }}
  BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }}
OpenReport an issue

Was this page helpful?

On this page