Environment Variables
Contentrain Studio is configured entirely through environment variables. Copy .env.example to .env and fill in the values for your deployment.
Core Application
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_SESSION_SECRET | Yes | -- | AES-256 cookie encryption key. Minimum 32 characters. |
NUXT_SESSION_SECRET_PREVIOUS | No | -- | Previous secret for key rotation. Set during migration window, remove after. |
NUXT_PUBLIC_SITE_URL | Yes | http://localhost:3000 | Public-facing application URL. Used for OAuth callbacks and email links. |
NUXT_PUBLIC_GITHUB_APP_SLUG | No | contentrain-studio | GitHub App slug for installation redirect URL. |
NUXT_PUBLIC_TEMPLATE_OWNER | No | Contentrain | GitHub org that owns starter kit template repos. |
NUXT_PUBLIC_BILLING_ENABLED | No | false | Billing UI visibility. Auto-derived on boot from configured payment plugins (true when Polar or Stripe is set). Set explicitly only to override. |
NODE_ENV | No | development | Set to production for production deployments. |
Session Secret
Generate a secure session secret:
openssl rand -base64 32Deployment Profile
Studio auto-detects its deployment profile at boot from whether the Enterprise bridge (ee/) loads and whether a payment plugin is configured. Set these only to pin behaviour explicitly.
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_DEPLOYMENT_PROFILE | No | -- (auto-detect) | managed | dedicated | on-premise | community. Server-side profile override. |
NUXT_PUBLIC_DEPLOYMENT_PROFILE | No | -- | Client-visible profile. managed | dedicated | on-premise | community. |
NUXT_PUBLIC_DEPLOYMENT_EDITION | No | -- | Client-visible edition. ee | agpl. |
NUXT_PUBLIC_DEPLOYMENT_BILLING_MODE | No | -- | Client-visible billing mode. polar | stripe | flat | off. |
Production Builds
Production (Nitro compiled output) freezes runtimeConfig.public, so the auto-derive plugin cannot mutate the snapshot. Set the three NUXT_PUBLIC_DEPLOYMENT_* variables explicitly in production to mirror the server-side resolveDeployment() result on the client. Dev mode does not need them.
Supabase (Auth + Database)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_SUPABASE_URL | Yes | -- | Supabase project URL (e.g., https://your-project.supabase.co). |
NUXT_SUPABASE_SERVICE_ROLE_KEY | Yes | -- | Service role key with admin database access. Keep private. |
NUXT_SUPABASE_ANON_KEY | Yes | -- | Anonymous key for client-side auth operations. |
Supabase OAuth (for local Supabase CLI)
These are only needed when running Supabase locally via the CLI:
| Variable | Required | Default | Description |
|---|---|---|---|
SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID | No | -- | GitHub OAuth client ID for Supabase auth. |
SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET | No | -- | GitHub OAuth client secret for Supabase auth. |
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID | No | -- | Google OAuth client ID for Supabase auth. |
SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET | No | -- | Google OAuth client secret for Supabase auth. |
GitHub App
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_GITHUB_APP_ID | Yes | -- | GitHub App ID (numeric). |
NUXT_GITHUB_CLIENT_ID | Yes | -- | GitHub App client ID. |
NUXT_GITHUB_CLIENT_SECRET | Yes | -- | GitHub App client secret. |
NUXT_GITHUB_PRIVATE_KEY | Yes | -- | Base64-encoded .pem private key file. |
NUXT_GITHUB_WEBHOOK_SECRET | Yes | -- | HMAC-SHA256 secret for webhook payload verification. |
Encoding the Private Key
base64 -i your-app.private-key.pem | tr -d '\n'AI (Anthropic)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_ANTHROPIC_API_KEY | No | -- | Operator-managed Anthropic API key for the Studio instance. If omitted, users need BYOA (Bring Your Own API key). |
CDN / Object Storage (Cloudflare R2)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_CDN_R2_ACCOUNT_ID | No | -- | Cloudflare account ID. Required for CDN and media features. |
NUXT_CDN_R2_ACCESS_KEY_ID | No | -- | R2 access key ID. |
NUXT_CDN_R2_SECRET_ACCESS_KEY | No | -- | R2 secret access key. |
NUXT_CDN_R2_BUCKET | No | contentrain-cdn | R2 bucket name. |
INFO
CDN and media library features require all four R2 variables to be set. If any are missing, useCDNProvider() and useMediaProvider() return null and those features are gracefully disabled.
Email (Resend)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_RESEND_API_KEY | No | -- | Resend API key for application emails (invites, notifications). |
RESEND_API_KEY | No | -- | Same key, read by local Supabase CLI for auth SMTP. |
NUXT_EMAIL_SENDER_ADDRESS | No | -- | Sender email address (e.g., [email protected]). |
NUXT_EMAIL_SENDER_NAME | No | -- | Sender display name (e.g., Contentrain Studio). |
Billing
Studio supports two payment plugins. Polar is the default provider; Stripe is supported as a secondary, legacy plugin. When both are configured, Polar takes precedence (the plugin registry preference order is polar -> stripe).
Polar (default)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_POLAR_ACCESS_TOKEN | No | -- | Polar organization access token (polar_oat_...). Activates the Polar plugin when set. |
NUXT_POLAR_WEBHOOK_SECRET | No | -- | Polar webhook signing secret (Standard Webhooks). |
NUXT_POLAR_STARTER_PRODUCT_ID | No | -- | Polar product ID for the Starter plan. |
NUXT_POLAR_PRO_PRODUCT_ID | No | -- | Polar product ID for the Pro plan. |
NUXT_POLAR_SERVER | No | production | Polar environment: sandbox for testing, production for live. |
Stripe (legacy / optional)
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_STRIPE_SECRET_KEY | No | -- | Stripe secret key. Activates the Stripe plugin when set. |
NUXT_STRIPE_WEBHOOK_SECRET | No | -- | Stripe webhook signing secret for event verification. |
NUXT_STRIPE_STARTER_PRICE_ID | No | -- | Stripe Price ID for the Starter plan. |
NUXT_STRIPE_PRO_PRICE_ID | No | -- | Stripe Price ID for the Pro plan. |
Self-Hosted Bypass
When no payment plugin (Polar or Stripe) is configured, Studio resolves to the on-premise profile (ee/ loaded) or community profile (ee/ missing) and hides the subscription UI. Core features work normally; premium features (CDN preview branches, custom variants, spam filter) remain gated by hasFeature().
Redis
| Variable | Required | Default | Description |
|---|---|---|---|
REDIS_URL | No | -- | Redis connection URL (e.g., redis://localhost:6379). Strongly recommended for multi-instance production rate limiting; dev falls back to in-memory. |
REDIS_CA_CERT | No | -- | Custom CA certificate for TLS Redis connections (rediss://). |
Sentry (Error & Performance Monitoring)
Optional. Leave NUXT_PUBLIC_SENTRY_DSN empty to disable Sentry entirely (the SDK no-ops on both client and server, and no telemetry leaves your infrastructure) -- this is the intended Community / self-host default.
| Variable | Required | Default | Description |
|---|---|---|---|
NUXT_PUBLIC_SENTRY_DSN | No | -- | Your Sentry project DSN. Empty disables Sentry completely. |
NUXT_PUBLIC_SENTRY_ENVIRONMENT | No | -- | Environment tag: development | staging | production. |
NUXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE | No | 0.1 | Performance-tracing sample rate. Errors are always captured at 100%. |
NUXT_PUBLIC_SENTRY_RELEASE | No | -- | Optional build/release identifier. |
These three are build-time only, for source map upload during nuxt build. When all three are set, readable stack traces are uploaded. SENTRY_AUTH_TOKEN is a secret -- never expose it to forked CI or the client bundle.
| Variable | Required | Default | Description |
|---|---|---|---|
SENTRY_ORG | No | -- | Sentry org slug (source map upload). |
SENTRY_PROJECT | No | -- | Sentry project slug (source map upload). |
SENTRY_AUTH_TOKEN | No | -- | Sentry auth token. Enables source map upload when present. |
Variable Resolution
Nuxt resolves runtime config variables using the NUXT_ prefix convention:
// nuxt.config.ts
runtimeConfig: {
sessionSecret: '', // -> NUXT_SESSION_SECRET
github: {
appId: '', // -> NUXT_GITHUB_APP_ID
clientId: '', // -> NUXT_GITHUB_CLIENT_ID
privateKey: '', // -> NUXT_GITHUB_PRIVATE_KEY
},
polar: {
accessToken: '', // -> NUXT_POLAR_ACCESS_TOKEN
server: 'production', // -> NUXT_POLAR_SERVER
},
public: {
siteUrl: 'http://localhost:3000', // -> NUXT_PUBLIC_SITE_URL
},
}Access in server code:
const config = useRuntimeConfig()
console.log(config.github.appId) // Server-only
console.log(config.public.siteUrl) // Both server and clientExample .env File
# Core
NUXT_SESSION_SECRET=your-random-32-character-string
NUXT_PUBLIC_SITE_URL=https://studio.yourdomain.com
# Supabase
NUXT_SUPABASE_URL=https://your-project.supabase.co
NUXT_SUPABASE_SERVICE_ROLE_KEY=eyJ...
NUXT_SUPABASE_ANON_KEY=eyJ...
# GitHub App
NUXT_GITHUB_APP_ID=123456
NUXT_GITHUB_CLIENT_ID=Iv1.abc123
NUXT_GITHUB_CLIENT_SECRET=abc123def456
NUXT_GITHUB_PRIVATE_KEY=LS0tLS1CRUdJTi...
NUXT_GITHUB_WEBHOOK_SECRET=whsec_abc123
# AI (optional)
NUXT_ANTHROPIC_API_KEY=sk-ant-...
# Email (optional)
NUXT_RESEND_API_KEY=re_abc123
NUXT_EMAIL_SENDER_ADDRESS=[email protected]
NUXT_EMAIL_SENDER_NAME=Contentrain Studio
# Billing — Polar (default; optional)
NUXT_POLAR_ACCESS_TOKEN=polar_oat_...
NUXT_POLAR_WEBHOOK_SECRET=your-polar-webhook-secret
NUXT_POLAR_STARTER_PRODUCT_ID=uuid-of-starter-product
NUXT_POLAR_PRO_PRODUCT_ID=uuid-of-pro-product
NUXT_POLAR_SERVER=productionRelated Pages
- Self-Hosting Guide -- deployment walkthrough
- Architecture -- how providers use these variables