Codapult
DocsBlogPricingPluginsDemo
Get Codapult
Logo

Build your SaaS with AI. Keep the architecture under control.

Get Codapult

Product

  • Pricing
  • Architecture
  • Modules
  • AI platform
  • Plugins

Developers

  • MCP
  • CLI
  • Documentation
  • Launch your SaaS
  • Build a B2B SaaS

Resources

  • Blog
  • FAQ

Connect

  • Contact
  • GitHub

Compare

  • SaaS template comparison
  • Codapult vs Supastarter
  • Codapult vs Makerkit
  • Codapult vs ShipFast
  • Codapult vs SaaSBold
  • Codapult vs Gravity
  • Codapult vs Nextbase
  • Codapult vs BuilderKit

Featured on

Codapult on LaunchNestCodapult on LaunchNestbetterlaunch.cobetterlaunch.coFeatured on LaunchBuffFeatured on LaunchBuffCodapult on PeerPushCodapult on PeerPushFeatured on LaunchItFeatured on LaunchIt
© 2026 Codapult·All rights reserved·Privacy Policy·Terms of Service
Full source code · One-time purchase · Self-host anywhere
All articles

Getting Started

  • Introduction
  • Quick Start
  • Your First 30 Minutes
  • Project Structure
  • License and Permitted Use
  • Starter Profiles and Recipes
  • Product Recipes

Configuration

  • Environment Variables
  • App Configuration
  • Which Modules Should I Enable?
  • Provider Matrix
  • Capability Coverage

Database

  • Database and Provider Guide
  • Database
  • Migrations

Authentication

  • Authentication
  • OAuth Providers
  • Two-Factor & Passwordless
  • Enterprise SSO (SAML)

Ai

  • AI Runtime Architecture and Evals
  • AI Features
  • Streaming Chat
  • RAG and Semantic Search
  • Quotas and Memory

Teams

  • Teams & Organizations
  • Permissions & RBAC
  • SCIM Provisioning

Security

  • Data Retention Policy
  • Security

Deployment

  • Enterprise E2E Evidence
  • Enterprise Production Readiness
  • Deployment, Backup, and Restore Runbook
  • Deployment
  • Troubleshooting

Payments

  • Payments & Billing
  • Stripe Setup
  • LemonSqueezy Setup
  • Polar Setup
  • Payment Webhooks

Api

  • API Layer
  • tRPC
  • GraphQL

Email

  • Email
  • Email Templates

Infrastructure

  • Infrastructure
  • Self-Hosting
  • File Storage
  • Docker
  • Background Jobs
  • Terraform & Pulumi
  • Kubernetes

Ui

  • UI & Theming

I18n

  • Internationalization

Content Management

  • Content Management

Admin

  • Admin Panel

Monitoring

  • Analytics & Monitoring

Modules

  • Module Architecture
  • Waitlist
  • Audit Log
  • White-Labeling
  • Workflow Automation
  • A/B Testing
  • Welcome Page
  • Referrals
  • GDPR Export and Deletion
  • Promotions
  • Outgoing Webhooks

Plugins

  • Plugin System
  • CRM Plugin
  • Helpdesk Plugin
  • Email Marketing Plugin

Upgrading

  • Upgrading Codapult

Developer Tools

  • AI Agents & IDEs
  • MCP Server
  • Testing
  • Build Your First Feature with Codapult MCP
  • How Guard Blocks an Architectural Regression
Configuration

Environment Variables

Complete reference for all environment variables used by Codapult, grouped by module.

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/config/env.ts for type-safe usage in server code. Always use env.* from src/config/env.ts 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

VariableRequiredDescription
DB_PROVIDERNoDatabase engine: "turso" (default) or "postgres"
TURSO_DATABASE_URLYes*Turso connection URL. Format: libsql://your-db.turso.io for cloud, or file:local.db for local development
TURSO_AUTH_TOKENYes**Auth token for Turso cloud databases
TURSO_API_TOKENNoTurso Platform API token — required for multi-region replication
TURSO_ORG_SLUGNoYour Turso organization slug — used with the Platform API
DATABASE_URLYes***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

VariableRequiredDescription
AUTH_PROVIDERNoAuth backend: "better-auth" (default), "kinde", or "none"
AUTH_MAGIC_LINKNoPasswordless sign-in via magic link. Defaults to "true"
AUTH_PASSKEYSNoWebAuthn / passkey sign-in. Defaults to "true"

Better-Auth variables

VariableRequiredDescription
BETTER_AUTH_SECRETYes*Session encryption secret. Generate with openssl rand -base64 32
BETTER_AUTH_URLNoAuth callback base URL. Defaults to http://localhost:3000

* Required when AUTH_PROVIDER=better-auth (the default).

Kinde variables

VariableRequiredDescription
KINDE_CLIENT_IDYes*Kinde application client ID
KINDE_CLIENT_SECRETYes*Kinde application client secret
KINDE_ISSUER_URLYes*Your Kinde domain, e.g. https://your-app.kinde.com
KINDE_SITE_URLNoSite URL for callbacks. Defaults to http://localhost:3000
KINDE_POST_LOGOUT_REDIRECT_URLNoRedirect after logout
KINDE_POST_LOGIN_REDIRECT_URLNoRedirect after login. Defaults to /dashboard

* Required when AUTH_PROVIDER=kinde.

OAuth providers (Better-Auth)

VariableRequiredDescription
GOOGLE_CLIENT_IDNoGoogle OAuth client ID — enable Google sign-in
GOOGLE_CLIENT_SECRETNoGoogle OAuth client secret
GITHUB_CLIENT_IDNoGitHub OAuth app client ID — enable GitHub sign-in
GITHUB_CLIENT_SECRETNoGitHub OAuth app client secret

Payments

VariableRequiredDescription
PAYMENT_PROVIDERNoPayment backend: "stripe" (default), "lemonsqueezy", or "polar"

Stripe variables

VariableRequiredDescription
STRIPE_SECRET_KEYYes*Stripe secret API key
STRIPE_WEBHOOK_SECRETYes*Webhook signing secret from Stripe dashboard
STRIPE_CONNECT_FEE_PERCENTNoPlatform fee percentage for Stripe Connect marketplace (default 10)
STRIPE_CONNECT_ONBOARDING_RETURN_URLNoReturn URL after Connect onboarding. Defaults to /dashboard/connect
STRIPE_CONNECT_ONBOARDING_REFRESH_URLNoRefresh URL for Connect onboarding. Defaults to /dashboard/connect

* Required when PAYMENT_PROVIDER=stripe (the default).

LemonSqueezy variables

VariableRequiredDescription
LEMONSQUEEZY_API_KEYYes*LemonSqueezy API key
LEMONSQUEEZY_STORE_IDYes*Your LemonSqueezy store ID
LEMONSQUEEZY_WEBHOOK_SECRETYes*Webhook signing secret

* Required when PAYMENT_PROVIDER=lemonsqueezy.

Polar variables

VariableRequiredDescription
POLAR_ACCESS_TOKENYes*Polar Personal Access Token
POLAR_WEBHOOK_SECRETYes*Webhook signing secret from Polar

* Required when PAYMENT_PROVIDER=polar.


AI

VariableRequiredDescription
OPENAI_API_KEYNoOpenAI API key — enables GPT models in AI chat
ANTHROPIC_API_KEYNoAnthropic API key — enables Claude models in AI chat
CUSTOM_AI_BASE_URLNoOpenAI-compatible custom endpoint; model must be declared in models.ts
CUSTOM_AI_API_KEYNoSecret for the OpenAI-compatible custom endpoint
EMBEDDING_PROVIDERNoEmbedding backend: "openai" (default) or "ollama"
VECTOR_STORE_PROVIDERNoVector storage: "sqlite" (default) or "memory" (useful for tests)
OLLAMA_BASE_URLNoOllama server URL. Defaults to http://localhost:11434
OLLAMA_EMBEDDING_MODELNoOllama 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 runtime. The runtime requires ENABLE_AI_CORE="true"; chat additionally requires ENABLE_AI_CHAT="true". RAG (retrieval-augmented generation) requires the core, an embedding provider, and ENABLE_AI_RAG="true".


Email

VariableRequiredDescription
RESEND_API_KEYNoResend API key — used for transactional emails, magic links, and drip campaigns. Emails are skipped when not set
EMAIL_FROMNoDefault sender address. Defaults to onboarding@resend.dev

Analytics

VariableRequiredDescription
POSTHOG_TOKENNoPostHog project API key
POSTHOG_HOSTNoPostHog instance URL. Defaults to https://us.i.posthog.com
ENABLE_ANALYTICSNoDefaults to "true". Useful when PostHog is not configured. Set to "false" to disable the built-in first-party analytics module.

Error Monitoring

VariableRequiredDescription
NEXT_PUBLIC_SENTRY_DSNNoSentry DSN — enables client, server, and edge error tracking
SENTRY_ORGNoSentry organization slug (used for source map uploads)
SENTRY_PROJECTNoSentry project name
SENTRY_AUTH_TOKENNoSentry auth token (used for source map uploads during build)
SENTRY_RELEASENoRelease identifier. Defaults to Vercel commit SHA on Vercel
SENTRY_ENVIRONMENTNoEnvironment label. Defaults to VERCEL_ENV or NODE_ENV
NEXT_PUBLIC_SENTRY_TRACE_TARGETSNoAdditional distributed tracing targets as a comma-separated list
SENTRY_IGNORE_ERRORSNoExtra comma-separated error-message substrings to ignore in Sentry

Storage

VariableRequiredDescription
STORAGE_PROVIDERNoFile storage backend: "local" (default), "s3", or "r2"

S3 / R2 variables

VariableRequiredDescription
S3_BUCKETYes*S3 bucket name
S3_REGIONNoAWS region. Defaults to "auto" (required for R2)
S3_ENDPOINTYes**Custom S3 endpoint URL (required for R2 and S3-compatible providers)
S3_ACCESS_KEY_IDYes*Access key ID
S3_SECRET_ACCESS_KEYYes*Secret access key
S3_PUBLIC_URLNoPublic 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

VariableRequiredDescription
JOB_PROVIDERNoJob runner: "memory" (default, in-process) or "bullmq" (Redis-backed)
REDIS_URLYes*Redis connection URL, e.g. redis://localhost:6379
JOB_QUEUE_NAMENoBullMQ queue name. Defaults to "codapult"
CODAPULT_WORKER_MODENoSet to "true" in a dedicated worker process or pod to start job handlers
CODAPULT_DISABLE_IN_PROCESS_JOBSNoSet to "true" on web processes when BullMQ workers run separately

* Required when JOB_PROVIDER=bullmq.

Use memory for development and bullmq for production workloads that need durable, concurrent job processing.


Notifications

VariableRequiredDescription
NOTIFICATION_TRANSPORTNoServer-side transport: "poll" (default), "sse", or "ws"
NOTIFICATION_WS_URLYes*WebSocket server URL, e.g. ws://localhost:3001
NOTIFICATION_WS_PORTNoPort for the WebSocket server. Defaults to 3001

* Required when NOTIFICATION_TRANSPORT=ws.


Enterprise SSO (SAML via BoxyHQ) and SCIM provisioning

VariableRequiredDescription
SSO_PROVIDERNoSSO engine: "jackson" (BoxyHQ Jackson) or "none" (default)
SSO_PRODUCTNoProduct identifier for SSO connections. Defaults to "codapult"
SSO_DB_ENGINENoJackson storage engine: "mem" (default), "sql", "mongo", or "redis"
SSO_DB_TYPENoDatabase type when SSO_DB_ENGINE=sql: "postgres" (default)
SSO_DB_URLYes*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

VariableRequiredDescription
NEXT_PUBLIC_APP_URLNoRuntime base URL. Defaults to http://localhost:3000. Access via appConfig.appUrl
NEXT_PUBLIC_APP_NAMENoTechnical project name (lowercase). Defaults to "codapult". Access via appConfig.appName
DEFAULT_MONTHLY_CREDITSNoMonthly AI usage credits per organization. Defaults to "100". Access via env.defaultMonthlyCredits

Referral Program

VariableRequiredDescription
REFERRAL_REWARD_AMOUNTNoReward amount per successful referral. Defaults to 0
REFERRAL_REWARD_TYPENoReward type: "credit" (default) or "discount"

Custom Domains

VariableRequiredDescription
CUSTOM_DOMAIN_CNAME_TARGETNoCNAME target for custom domain verification (e.g. cname.yourdomain.com)

Support Widget

VariableRequiredDescription
SUPPORT_PROVIDERNoSupport chat provider: "crisp", "intercom", or "none" (default)
CRISP_WEBSITE_IDYes*Crisp website ID
INTERCOM_APP_IDYes**Intercom app ID

* Required when SUPPORT_PROVIDER=crisp. ** Required when SUPPORT_PROVIDER=intercom.


OpenTelemetry

VariableRequiredDescription
OTEL_EXPORTER_OTLP_ENDPOINTNoOTLP collector endpoint, e.g. http://localhost:4318. Tracing is disabled when not set
OTEL_SERVICE_NAMENoService name in traces. Defaults to appConfig.appName
OTEL_TRACES_SAMPLE_RATENoSampling rate from 0 to 1. Defaults to "0.1" (10%)
OTEL_EXPORTER_OTLP_HEADERSNoHeaders for the OTLP exporter, e.g. Authorization=Bearer token
LOG_LEVELNoLogger minimum level: "trace", "debug", "info", "warn", "error", or "fatal"

Marketing-only / Checkout

VariableRequiredDescription
CHECKOUT_URL_*NoExternal checkout URL for the license tier

These link CTA buttons directly to an external checkout page.

API checkout variant IDs

VariableRequiredDescription
CHECKOUT_VARIANT_*NoProvider variant/price ID for the tier

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, LemonSqueezy, and Polar by changing PAYMENT_PROVIDER and the variant IDs.

Priority: CHECKOUT_VARIANT_* (API session) > CHECKOUT_URL_* (direct link) > fallback (/sign-up).

All checkout variables are only used in marketing-only mode (APP_MODE="landing"). See Marketing / Guest Checkout for details.


Application Modes

VariableRequiredDescription
APP_MODENo"app" (default), "landing" for marketing-only mode, or "demo" for a read-only dashboard
DEMO_URLNoURL of the demo deployment — shown on the landing page

Feature Toggles

Feature-toggle defaults depend on APP_MODE: the normal app mode enables most features, while landing mode disables app-only surfaces by default. Set a variable to "false" to turn a feature off explicitly. Disabled features are hidden from the navigation and their pages/API routes return 404 (enforced in src/proxy.ts). Features marked with † additionally require AUTH_PROVIDER ≠ none.

VariableRequiredDescription
ENABLE_API_DOCSNoInteractive OpenAPI reference at /docs/api†
ENABLE_HELP_CENTERNoHelp center / documentation (MDX)
ENABLE_BLOGNoMDX blog at /blog
ENABLE_WAITLISTNoPublic /waitlist landing and /admin/waitlist
ENABLE_CHANGELOGNo"true" / "file" — curated CHANGELOG.md (default). "git" — from git tags/commits. "false" — disabled†
ENABLE_FEATURE_REQUESTSNoFeature request voting board†
ENABLE_AI_CORENoShared AI gateway and server-side AI modules†
ENABLE_AI_CHATNoAI chat assistant (Vercel AI SDK, streaming); requires AI core†
ENABLE_AI_RAGNoRAG indexing and retrieval; opt-in and requires AI core†
ENABLE_AI_AGENTSNoAI agents and tool execution; requires AI core†
ENABLE_AI_BATCHNoAsynchronous AI batch processing; requires AI core†
ENABLE_AI_PLAYGROUNDNoAI playground and model comparison; requires AI core†
ENABLE_TEAMSNoOrganizations, multi-tenancy, team invitations†
ENABLE_REFERRALSNoReferral / affiliate program†
ENABLE_PROMOTIONSNoPromotion codes and product-specific pricing overrides
ENABLE_ANALYTICSNoSelf-serve built-in first-party analytics module and dashboard
ENABLE_WORKFLOWSNoEvent-triggered workflow automation
ENABLE_WEBHOOKSNoOutgoing webhooks (HMAC signed)
ENABLE_AUDIT_LOGNoUser-facing activity / audit log
ENABLE_REPORTSNoScheduled email reports (daily/weekly/monthly)
ENABLE_ONBOARDINGNoInteractive onboarding tours
ENABLE_BRANDINGNoPer-org branding / white-labeling
ENABLE_EXPERIMENTSNoA/B testing framework (weighted variants)
ENABLE_DRIP_CAMPAIGNSNoEmail drip campaigns
ENABLE_TWO_FACTORNoTOTP-based two-factor authentication†
ENABLE_PLUGINSNoPremium plugin marketplace at /plugins and /dashboard/plugins

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 APP_MODE="landing" to run in marketing-only 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.
Product RecipesApp Configuration