Environment Variables
Every environment variable, grouped by feature. Secrets live here — never in config files or version control.
Copy .env.example to .env.local and fill in what you need. Only the
variables for the features you enable are required; analytics and monitoring
stay off until their keys are present.
Core
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Yes | Postgres connection string |
BETTER_AUTH_SECRET | Yes | Auth signing secret (openssl rand -base64 32) |
BETTER_AUTH_URL | Yes | Web app origin serving auth routes |
WEB_URL | Yes | Public web app URL |
API_URL | Yes | Public API origin |
NEXT_PUBLIC_API_URL | Yes | API URL exposed to the browser |
PLUGIN_SLUG | Yes | Plugin identifier (matches the Admin Module) |
Auth
| Variable | Description |
|---|---|
AUTH_MAGIC_LINK / AUTH_PASSKEYS / AUTH_TWO_FACTOR | Feature toggles (default on) |
AUTH_REQUIRE_EMAIL_VERIFICATION | Require verified email before access |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | Google social login |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | GitHub social login |
Billing
LemonSqueezy is the default; only the selected provider's vars are required.
| Variable | Description |
|---|---|
LEMONSQUEEZY_API_KEY | API key |
LEMONSQUEEZY_STORE_ID | Store id |
LEMONSQUEEZY_WEBHOOK_SECRET | Webhook signing secret |
Webhook URL to register: POST {API_URL}/webhooks/billing.
Email (fallback chain)
The chain is resend → nodemailer → plunk → maileroo → mailgun. Configure the
providers you want; with none set, emails log to the console in dev.
| Variable | Provider |
|---|---|
EMAIL_FROM | Default sender (all providers) |
RESEND_API_KEY | Resend (primary) |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS | Nodemailer SMTP |
PLUNK_API_KEY | Plunk |
MAILEROO_API_KEY | Maileroo |
MAILGUN_API_KEY / MAILGUN_DOMAIN / MAILGUN_BASE_URL | Mailgun |
EMAIL_RETRY_ATTEMPTS / EMAIL_RETRY_BASE_MS | Per-provider retry/backoff |
Storage (S3-compatible)
Off until STORAGE_ACCESS_KEY_ID + STORAGE_BUCKET are set.
| Variable | Description |
|---|---|
STORAGE_PROVIDER | r2 / s3 / minio (informational) |
STORAGE_BUCKET | Bucket name |
STORAGE_ACCESS_KEY_ID / STORAGE_SECRET_ACCESS_KEY | Credentials |
STORAGE_REGION | auto for R2; a region for S3 |
STORAGE_ENDPOINT | Custom endpoint (R2/MinIO) |
STORAGE_PUBLIC_URL | Public base URL for objects |
STORAGE_MAX_UPLOAD_BYTES / STORAGE_PRESIGN_TTL | Upload guards |
Analytics (GA4)
Off unless a measurement id is set. Privacy-first and consent-aware.
| Variable | Description |
|---|---|
NEXT_PUBLIC_GA_MEASUREMENT_ID | GA4 id (G-XXXXXXXXXX) |
NEXT_PUBLIC_ANALYTICS_ENABLED | Master switch (default on when id present) |
NEXT_PUBLIC_ANALYTICS_REQUIRE_CONSENT | Require cookie consent (default true) |
Monitoring (Sentry)
Off unless a DSN is set.
| Variable | Description |
|---|---|
SENTRY_DSN | Server DSN |
NEXT_PUBLIC_SENTRY_DSN | Browser DSN |
SENTRY_ENABLED | Master switch (default on when DSN present) |
SENTRY_TRACES_SAMPLE_RATE | Performance sampling (0.0–1.0) |
SENTRY_AUTH_TOKEN / SENTRY_ORG / SENTRY_PROJECT | Source-map upload (optional) |
Background jobs
| Variable | Description |
|---|---|
QSTASH_TOKEN | QStash publish token |
QSTASH_CURRENT_SIGNING_KEY / QSTASH_NEXT_SIGNING_KEY | Inbound signature verification |
TRIGGER_SECRET_KEY | Trigger.dev (optional runner) |
Admin connector
| Variable | Description |
|---|---|
CONNECTOR_SECRET | Shared service token (openssl rand -base64 48) |
ADMIN_CONNECTOR_URL | Admin Module connector endpoint |
Plugin public surface
| Variable | Description |
|---|---|
PLUGIN_PUBLIC_API_KEY | Publishable key shipped inside the plugin |
PUBLIC_RATE_LIMIT_WINDOW_MS / PUBLIC_RATE_LIMIT_MAX | Public surface rate limits |
Keep every secret in the environment — never commit .env.local or hardcode
values in packages/config.