Settings live in three places:
apps/web. They hold values that change per environment.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.public.config row in the database. It holds the billing provider and three on/off switches the database itself checks.| 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.
| 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. |
| 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 |
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.
Each of these has its own page:
NEXT_PUBLIC_BILLING_PROVIDER and the Stripe and Lemon Squeezy keys: Stripe and Lemon Squeezy.MAILER_PROVIDER, EMAIL_*, RESEND_API_KEY, CONTACT_EMAIL: Email.CMS_CLIENT and 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.
| 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 |
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.