Configuration
Where settings live: the env files, the typed config files in apps/web/config, and the database config row.
Settings live in three places:
- Env files in
apps/web. They hold values that change per environment. - Config files in
apps/web/config. They read the env values, validate them with Zod and export typed objects. An invalid value stops the app at startup or at build time. - The
public.configrow in the database. It holds the billing provider and three on/off switches the database itself checks.
Env files
| File | Committed | Holds |
|---|---|---|
apps/web/.env | Yes | Public values shared by every environment: site name, auth methods, feature flags |
apps/web/.env.development | Yes | Local Supabase URL and keys, local mail server |
apps/web/.env.production | Yes | Public production values only |
apps/web/.env.test | Yes | Values for the CI and end-to-end test build |
apps/web/.env.local | No (ignored by Git) | Your secrets on your machine |
Put secrets (Supabase secret key, Stripe keys, mail passwords) in .env.local locally and in your host's environment settings in production. Never in a committed file.
NEXT_PUBLIC_* values are read when the server starts, so restart pnpm dev after you change one.
Site
| Variable | Notes |
|---|---|
NEXT_PUBLIC_SITE_URL | Must be https:// in a production build (config/app.config.ts fails the build otherwise) |
NEXT_PUBLIC_PRODUCT_NAME, NEXT_PUBLIC_SITE_TITLE, NEXT_PUBLIC_SITE_DESCRIPTION | Name and default metadata |
NEXT_PUBLIC_DEFAULT_THEME_MODE | light, dark or system |
NEXT_PUBLIC_THEME_COLOR, NEXT_PUBLIC_THEME_COLOR_DARK | Browser theme colours. They must differ. |
Supabase
| Variable | Notes |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Project URL |
NEXT_PUBLIC_SUPABASE_PUBLIC_KEY | Public (anon) key |
SUPABASE_SECRET_KEY | Secret key. Read only in server-only modules; it bypasses row-level security |
SUPABASE_DB_WEBHOOK_SECRET | Shared secret the database webhook sends to /api/db/webhook |
Feature flags
config/feature-flags.config.ts reads these. The code default applies when a variable is not set.
| Variable | Code default | In .env |
|---|---|---|
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS | true | true |
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION | true | true |
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY | false | false |
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_DELETION | false | true |
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION | false | true |
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING | false | true |
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING | false | true |
NEXT_PUBLIC_ENABLE_NOTIFICATIONS | true | not set |
NEXT_PUBLIC_REALTIME_NOTIFICATIONS | false | not set |
NEXT_PUBLIC_ENABLE_THEME_TOGGLE | true | true |
NEXT_PUBLIC_ENABLE_VERSION_UPDATER | false | not set |
NEXT_PUBLIC_LANGUAGE_PRIORITY | application | application |
With NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY=true, the personal workspace is skipped: users land in their last team, or on the create-team page if they have none.
Other areas
Each of these has its own page:
- Sign-in methods, captcha and password rules: Authentication.
NEXT_PUBLIC_BILLING_PROVIDERand the Stripe and Lemon Squeezy keys: Stripe and Lemon Squeezy.MAILER_PROVIDER,EMAIL_*,RESEND_API_KEY,CONTACT_EMAIL: Email.CMS_CLIENTand the content path: Blog, docs and changelog.NEXT_PUBLIC_DEMO_*: Live demo.
A few more that are off by default:
| Variable | Effect |
|---|---|
NEXT_PUBLIC_MONITORING_PROVIDER | sentry turns on Sentry (with NEXT_PUBLIC_SENTRY_DSN). Empty logs errors to the console. |
ENABLE_STRICT_CSP | true turns on the strict Content Security Policy in apps/web/proxy.ts. Default false. |
ENABLE_REACT_COMPILER | true turns on the React Compiler in next.config.mjs |
The NEXT_PUBLIC_KIT_* variables and config/kit-offer.config.ts drive the kit's own sales page (prices, payment links, demo link). Replace them with your own offer, or remove that page, when you build your product.
Config files
| File | What it sets |
|---|---|
app.config.ts | Name, title, description, URL, theme, locale |
auth.config.ts | Sign-in methods, captcha key, terms checkbox, identity linking |
feature-flags.config.ts | The flags above |
paths.config.ts | Routes for sign-in, the app, settings, billing and invitations |
billing.config.ts | Your products and plans. It re-exports billing.sample.config.ts until you replace it |
personal-account-navigation.config.tsx, team-account-navigation.config.tsx | Sidebar links |
demo.config.ts | Live demo mode |
kit-offer.config.ts | The kit's own sales page |
The database config row
apps/web/supabase/schemas/02-config.sql creates public.config with enable_team_accounts, enable_account_billing, enable_team_account_billing (all true) and billing_provider (stripe). If you switch to Lemon Squeezy, update billing_provider here as well as NEXT_PUBLIC_BILLING_PROVIDER.