Codapult uses environment variables for secrets, provider selection, and per-environment configuration. Copy .env.example to .env.local and fill in the values relevant to your setup.
cp .env.example .env.local
Variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Never put secrets in NEXT_PUBLIC_ variables.
All env vars are accessed through src/lib/config.ts for type-safe usage in server code. Always use env.* from @/lib/config instead of reading process.env directly — this ensures consistent defaults and type safety. See the App Configuration page for the full env object reference.
Database
| Variable | Required | Description |
|---|
DB_PROVIDER | No | Database engine: "turso" (default) or "postgres" |
TURSO_DATABASE_URL | Yes* | Turso connection URL. Format: libsql://your-db.turso.io for cloud, or file:local.db for local development |
TURSO_AUTH_TOKEN | Yes** | Auth token for Turso cloud databases |
TURSO_API_TOKEN | No | Turso Platform API token — required for multi-region replication |
TURSO_ORG_SLUG | No | Your Turso organization slug — used with the Platform API |
DATABASE_URL | Yes*** | PostgreSQL connection string. Format: postgresql://user:password@host:5432/dbname?sslmode=require |
* Required when DB_PROVIDER=turso (the default).
** Required for Turso cloud databases. Not needed for local file: URLs.
*** Required when DB_PROVIDER=postgres.
Authentication
| Variable | Required | Description |
|---|
AUTH_PROVIDER | No | Auth backend: "better-auth" (default), "kinde", or "none" |
Better-Auth variables
| Variable | Required | Description |
|---|
BETTER_AUTH_SECRET | Yes* | Session encryption secret. Generate with openssl rand -base64 32 |
BETTER_AUTH_URL | No | Auth callback base URL. Defaults to http://localhost:3000 |
* Required when AUTH_PROVIDER=better-auth (the default).
Kinde variables
| Variable | Required | Description |
|---|
KINDE_CLIENT_ID | Yes* | Kinde application client ID |
KINDE_CLIENT_SECRET | Yes* | Kinde application client secret |
KINDE_ISSUER_URL | Yes* | Your Kinde domain, e.g. https://your-app.kinde.com |
KINDE_SITE_URL | No | Site URL for callbacks. Defaults to http://localhost:3000 |
KINDE_POST_LOGOUT_REDIRECT_URL | No | Redirect after logout |
KINDE_POST_LOGIN_REDIRECT_URL | No | Redirect after login. Defaults to /dashboard |
* Required when AUTH_PROVIDER=kinde.
OAuth providers (Better-Auth)
| Variable | Required | Description |
|---|
GOOGLE_CLIENT_ID | No | Google OAuth client ID — enable Google sign-in |
GOOGLE_CLIENT_SECRET | No | Google OAuth client secret |
GITHUB_CLIENT_ID | No | GitHub OAuth app client ID — enable GitHub sign-in |
GITHUB_CLIENT_SECRET | No | GitHub OAuth app client secret |
Payments
| Variable | Required | Description |
|---|
PAYMENT_PROVIDER | No | Payment backend: "stripe" (default), "lemonsqueezy", or "polar" |
Stripe variables
| Variable | Required | Description |
|---|
STRIPE_SECRET_KEY | Yes* | Stripe secret API key |
STRIPE_WEBHOOK_SECRET | Yes* | Webhook signing secret from Stripe dashboard |
NEXT_PUBLIC_STRIPE_CONNECT_FEE_PERCENT | No | Platform fee percentage for Stripe Connect marketplace (overrides appConfig.payments.stripeConnectFeePercent, default 10) |
STRIPE_CONNECT_ONBOARDING_RETURN_URL | No | Return URL after Connect onboarding. Defaults to /dashboard/connect |
STRIPE_CONNECT_ONBOARDING_REFRESH_URL | No | Refresh URL for Connect onboarding. Defaults to /dashboard/connect |
* Required when PAYMENT_PROVIDER=stripe (the default).
LemonSqueezy variables
| Variable | Required | Description |
|---|
LEMONSQUEEZY_API_KEY | Yes* | LemonSqueezy API key |
LEMONSQUEEZY_STORE_ID | Yes* | Your LemonSqueezy store ID |
LEMONSQUEEZY_WEBHOOK_SECRET | Yes* | Webhook signing secret |
* Required when PAYMENT_PROVIDER=lemonsqueezy.
Polar variables
| Variable | Required | Description |
|---|
POLAR_ACCESS_TOKEN | Yes* | Polar Personal Access Token |
POLAR_WEBHOOK_SECRET | Yes* | Webhook signing secret from Polar |
* Required when PAYMENT_PROVIDER=polar.
AI
| Variable | Required | Description |
|---|
OPENAI_API_KEY | No | OpenAI API key — enables GPT models in AI chat |
ANTHROPIC_API_KEY | No | Anthropic API key — enables Claude models in AI chat |
EMBEDDING_PROVIDER | No | Embedding backend: "openai" (default) or "ollama" |
VECTOR_STORE_PROVIDER | No | Vector storage: "sqlite" (default) or "memory" (useful for tests) |
OLLAMA_BASE_URL | No | Ollama server URL. Defaults to http://localhost:11434 |
OLLAMA_EMBEDDING_MODEL | No | Ollama model for embeddings. Defaults to nomic-embed-text |
At least one of OPENAI_API_KEY or ANTHROPIC_API_KEY is needed to use the AI chat feature. RAG (retrieval-augmented generation) requires an embedding provider to be configured.
Email
| Variable | Required | Description |
|---|
RESEND_API_KEY | No | Resend API key — used for transactional emails, magic links, and drip campaigns. Emails are skipped when not set |
EMAIL_FROM | No | Default sender address. Defaults to [email protected] |
Analytics
| Variable | Required | Description |
|---|
NEXT_PUBLIC_POSTHOG_KEY | No | PostHog project API key |
NEXT_PUBLIC_POSTHOG_HOST | No | PostHog instance URL. Defaults to https://us.i.posthog.com |
NEXT_PUBLIC_ANALYTICS_ENABLED | No | Set to "true" to enable the built-in first-party analytics module. Useful when PostHog is not configured |
Error Monitoring
| Variable | Required | Description |
|---|
NEXT_PUBLIC_SENTRY_DSN | No | Sentry DSN — enables client, server, and edge error tracking |
SENTRY_ORG | No | Sentry organization slug (used for source map uploads) |
SENTRY_PROJECT | No | Sentry project name |
SENTRY_AUTH_TOKEN | No | Sentry auth token (used for source map uploads during build) |
Storage
| Variable | Required | Description |
|---|
STORAGE_PROVIDER | No | File storage backend: "local" (default), "s3", or "r2" |
S3 / R2 variables
| Variable | Required | Description |
|---|
S3_BUCKET | Yes* | S3 bucket name |
S3_REGION | No | AWS region. Defaults to "auto" (required for R2) |
S3_ENDPOINT | Yes** | Custom S3 endpoint URL (required for R2 and S3-compatible providers) |
S3_ACCESS_KEY_ID | Yes* | Access key ID |
S3_SECRET_ACCESS_KEY | Yes* | Secret access key |
S3_PUBLIC_URL | No | Public URL prefix for uploaded files (e.g. CDN domain) |
* Required when STORAGE_PROVIDER=s3 or STORAGE_PROVIDER=r2.
** Required for Cloudflare R2 and other S3-compatible providers.
Background Jobs
| Variable | Required | Description |
|---|
JOB_PROVIDER | No | Job runner: "memory" (default, in-process) or "bullmq" (Redis-backed) |
REDIS_URL | Yes* | Redis connection URL, e.g. redis://localhost:6379 |
JOB_QUEUE_NAME | No | BullMQ queue name. Defaults to "codapult" |
* Required when JOB_PROVIDER=bullmq.
Use memory for development and bullmq for production workloads that need durable, concurrent job processing.
Notifications
| Variable | Required | Description |
|---|
NOTIFICATION_TRANSPORT | No | Server-side transport: "poll" (default), "sse", or "ws" |
NEXT_PUBLIC_WS_URL | Yes* | WebSocket server URL, e.g. ws://localhost:3001 |
WS_PORT | No | Port for the WebSocket server. Defaults to 3001 |
* Required when NOTIFICATION_TRANSPORT=ws.
Enterprise SSO (SAML)
| Variable | Required | Description |
|---|
SSO_PROVIDER | No | SSO engine: "jackson" (BoxyHQ Jackson, default) |
SSO_PRODUCT | No | Product identifier for SSO connections. Defaults to "codapult" |
SSO_DB_ENGINE | No | Jackson storage engine: "mem" (default), "sql", "mongo", or "redis" |
SSO_DB_TYPE | No | Database type when SSO_DB_ENGINE=sql: "postgres" (default) |
SSO_DB_URL | Yes* | Database URL for Jackson persistence |
* Required when SSO_DB_ENGINE=sql (recommended for production).
For development, Jackson defaults to in-memory storage. For production, use a Postgres database for durable SSO connections.
App
| Variable | Required | Description |
|---|
NEXT_PUBLIC_APP_URL | No | Runtime base URL. Defaults to http://localhost:3000. Access via appConfig.appUrl |
NEXT_PUBLIC_APP_NAME | No | Technical project name (lowercase). Defaults to "codapult". Access via appConfig.appName |
DEFAULT_MONTHLY_CREDITS | No | Monthly AI usage credits per organization. Defaults to "100". Access via env.defaultMonthlyCredits |
Referral Program
| Variable | Required | Description |
|---|
REFERRAL_REWARD_AMOUNT | No | Reward amount per successful referral. Defaults to 0 |
REFERRAL_REWARD_TYPE | No | Reward type: "credit" (default) or "discount" |
Custom Domains
| Variable | Required | Description |
|---|
CUSTOM_DOMAIN_CNAME_TARGET | No | CNAME target for custom domain verification (e.g. cname.yourdomain.com) |
Support Widget
| Variable | Required | Description |
|---|
NEXT_PUBLIC_SUPPORT_PROVIDER | No | Support chat provider: "crisp", "intercom", or "none" (default) |
NEXT_PUBLIC_CRISP_WEBSITE_ID | Yes* | Crisp website ID |
NEXT_PUBLIC_INTERCOM_APP_ID | Yes** | Intercom app ID |
* Required when NEXT_PUBLIC_SUPPORT_PROVIDER=crisp.
** Required when NEXT_PUBLIC_SUPPORT_PROVIDER=intercom.
OpenTelemetry
| Variable | Required | Description |
|---|
OTEL_EXPORTER_OTLP_ENDPOINT | No | OTLP collector endpoint, e.g. http://localhost:4318. Tracing is disabled when not set |
OTEL_SERVICE_NAME | No | Service name in traces. Defaults to appConfig.appName |
OTEL_TRACES_SAMPLE_RATE | No | Sampling rate from 0 to 1. Defaults to "0.1" (10%) |
OTEL_EXPORTER_OTLP_HEADERS | No | Headers for the OTLP exporter, e.g. Authorization=Bearer token |
Showcase / Checkout (AUTH_PROVIDER=none)
| Variable | Required | Description |
|---|
CHECKOUT_URL_STARTER | No | External checkout URL for the Starter license tier |
CHECKOUT_URL_PRO | No | External checkout URL for the Pro license tier |
CHECKOUT_URL_ENTERPRISE | No | External checkout URL for the Enterprise tier |
CHECKOUT_URL_PLUGIN_AI_KIT | No | Checkout URL for the AI Kit plugin |
CHECKOUT_URL_PLUGIN_CRM | No | Checkout URL for the CRM plugin |
CHECKOUT_URL_PLUGIN_HELPDESK | No | Checkout URL for the Helpdesk plugin |
CHECKOUT_URL_PLUGIN_EMAIL_MARKETING | No | Checkout URL for the Email Marketing plugin |
CHECKOUT_URL_PLUGIN_BUNDLE | No | Checkout URL for the plugin bundle |
These link CTA buttons directly to an external checkout page.
API checkout variant IDs
| Variable | Required | Description |
|---|
CHECKOUT_VARIANT_STARTER | No | Provider variant/price ID for the Starter tier |
CHECKOUT_VARIANT_PRO | No | Provider variant/price ID for the Pro tier |
CHECKOUT_VARIANT_ENTERPRISE | No | Provider variant/price ID for the Enterprise tier |
CHECKOUT_VARIANT_PLUGIN_AI_KIT | No | Variant/price ID for the AI Kit plugin |
CHECKOUT_VARIANT_PLUGIN_CRM | No | Variant/price ID for the CRM plugin |
CHECKOUT_VARIANT_PLUGIN_HELPDESK | No | Variant/price ID for the Helpdesk plugin |
CHECKOUT_VARIANT_PLUGIN_EMAIL_MARKETING | No | Variant/price ID for the Email Marketing plugin |
CHECKOUT_VARIANT_PLUGIN_BUNDLE | No | Variant/price ID for the plugin bundle |
When set, CTA buttons link to /api/checkout?product=<key>, which creates a checkout session via the active PAYMENT_PROVIDER adapter and redirects. This is provider-agnostic — switch between Stripe and LemonSqueezy by changing PAYMENT_PROVIDER and the variant IDs.
Priority: CHECKOUT_URL_* (direct link) > CHECKOUT_VARIANT_* (API session) > fallback (/sign-up or /#plugins).
All checkout variables are only used in showcase mode (AUTH_PROVIDER=none). See Marketing / Showcase Checkout for details.
Demo Mode
| Variable | Required | Description |
|---|
NEXT_PUBLIC_DEMO_MODE | No | Set to "true" to enable demo mode (read-only dashboard) |
DEMO_URL | No | URL of the demo deployment — shown on the landing page |
Feature Toggles
| Variable | Required | Description |
|---|
ENABLE_API_DOCS | No | Set to "false" to disable the interactive API docs page. Defaults to enabled |
ENABLE_HELP_CENTER | No | Set to "false" to disable the help center. Defaults to enabled |
ENABLE_CHANGELOG | No | "true" / "file" — curated CHANGELOG.md (default). "git" — from git tags/commits. "false" — disabled |
ENABLE_FEATURE_REQUESTS | No | Set to "false" to disable the feature request board. Defaults to enabled |
Tips
- Start minimal. With the default adapters (Turso + Better-Auth + Stripe), only three variables are required:
TURSO_DATABASE_URL, BETTER_AUTH_SECRET (≥32 characters), and STRIPE_SECRET_KEY. Use test keys from the Stripe dashboard for development. Emails are skipped when RESEND_API_KEY is not set.
- Skip Stripe for now? Set
AUTH_PROVIDER=none to run in showcase/marketing mode — only TURSO_DATABASE_URL is required.
- Use the setup wizard. Run
npx @codapult/cli setup to generate .env.local interactively.
- Adapter defaults. If you omit a provider variable (e.g.
AUTH_PROVIDER), Codapult falls back to the default adapter — no configuration needed.
- Conditional requirements. Variables marked "Yes*" are only required when you select their corresponding provider or feature.