Environment Variables Reference for the Tanstack Start Supabase SaaS Kit
Complete reference for all environment variables in the Tanstack Start Supabase SaaS Kit, including Supabase, Stripe, email, and feature flag configuration.
This page documents all environment variables used by the Tanstack Start Supabase SaaS Kit. Variables are organized by category and include their purpose, required status, and default values.
Environment File Structure
| File | Purpose | Git Status |
|---|---|---|
.env | Shared settings across all environments | Committed |
.env.development | Development-specific overrides | Committed |
.env.production | Production-specific settings | Committed |
.env.local | Local secrets and overrides | Git-ignored |
Priority order: .env.local > .env.development/.env.production > .env
Required Variables
These variables must be set for the application to start:
# Supabase (required)VITE_SUPABASE_URL=https://yourproject.supabase.coVITE_SUPABASE_PUBLIC_KEY=your-public-keySUPABASE_SECRET_KEY=your-service-role-key# App identity (required)VITE_SITE_URL=https://yourapp.comVITE_PRODUCT_NAME=Your ProductVITE_SITE_TITLE="Your Product - Tagline"VITE_SITE_DESCRIPTION="Your product description"Core Configuration
Site Identity
VITE_SITE_URL=https://example.comVITE_PRODUCT_NAME=MakerkitVITE_SITE_TITLE="Makerkit - Build SaaS Faster"VITE_SITE_DESCRIPTION="Production-ready SaaS starter kit"VITE_DEFAULT_LOCALE=en| Variable | Required | Description |
|---|---|---|
VITE_SITE_URL | Yes | Full URL with protocol |
VITE_PRODUCT_NAME | Yes | Product name shown in UI |
VITE_SITE_TITLE | Yes | Browser title and SEO |
VITE_SITE_DESCRIPTION | Yes | Meta description |
VITE_DEFAULT_LOCALE | No | Default language (default: en) |
Theme
VITE_DEFAULT_THEME_MODE=lightVITE_THEME_COLOR="#ffffff"VITE_THEME_COLOR_DARK="#0a0a0a"VITE_ENABLE_THEME_TOGGLE=true| Variable | Options | Default | Description |
|---|---|---|---|
VITE_DEFAULT_THEME_MODE | light, dark, system | light | Initial theme |
VITE_THEME_COLOR | Hex color | Required | Light theme color |
VITE_THEME_COLOR_DARK | Hex color | Required | Dark theme color |
VITE_ENABLE_THEME_TOGGLE | true, false | true | Allow theme switching |
Supabase Configuration
VITE_SUPABASE_URL=https://yourproject.supabase.coVITE_SUPABASE_PUBLIC_KEY=your-public-keySUPABASE_SECRET_KEY=your-service-role-keySUPABASE_DB_WEBHOOK_SECRET=your-webhook-secret| Variable | Required | Description |
|---|---|---|
VITE_SUPABASE_URL | Yes | Supabase project URL |
VITE_SUPABASE_PUBLIC_KEY | Yes | Public anon key |
SUPABASE_SECRET_KEY | Yes | Service role key (keep secret) |
SUPABASE_DB_WEBHOOK_SECRET | No | Webhook verification secret |
Legacy Key Names
If you're using a version prior to 2.12.0, use VITE_SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY instead.
Authentication
VITE_AUTH_PASSWORD=trueVITE_AUTH_MAGIC_LINK=falseVITE_AUTH_OTP=falseVITE_AUTH_PASSKEY=falseVITE_AUTH_IDENTITY_LINKING=falseVITE_CAPTCHA_SITE_KEY=CAPTCHA_SECRET_TOKEN=VITE_CAPTCHA_WIDGET_SIZE=invisibleVITE_DISPLAY_TERMS_AND_CONDITIONS_CHECKBOX=false| Variable | Default | Description |
|---|---|---|
VITE_AUTH_PASSWORD | true | Enable password auth |
VITE_AUTH_MAGIC_LINK | false | Enable magic link auth |
VITE_AUTH_OTP | false | Enable OTP auth |
VITE_AUTH_PASSKEY | false | Enable passkey (WebAuthn) auth |
VITE_AUTH_IDENTITY_LINKING | false | Allow identity linking |
VITE_CAPTCHA_SITE_KEY | - | Cloudflare Turnstile site key |
CAPTCHA_SECRET_TOKEN | - | Cloudflare Turnstile secret |
VITE_CAPTCHA_WIDGET_SIZE | invisible | Turnstile widget size. Set to normal or compact with a Managed site key |
VITE_DISPLAY_TERMS_AND_CONDITIONS_CHECKBOX | false | Show terms checkbox |
Password Requirements
VITE_PASSWORD_REQUIRE_UPPERCASE=falseVITE_PASSWORD_REQUIRE_NUMBERS=falseVITE_PASSWORD_REQUIRE_SPECIAL_CHARS=falseNavigation and Layout
VITE_USER_NAVIGATION_STYLE=sidebarVITE_HOME_SIDEBAR_COLLAPSED=falseVITE_SIDEBAR_COLLAPSIBLE_STYLE=iconVITE_ENABLE_SIDEBAR_TRIGGER=true| Variable | Options | Default | Description |
|---|---|---|---|
VITE_USER_NAVIGATION_STYLE | sidebar, header | sidebar | App navigation layout (personal + team) |
VITE_HOME_SIDEBAR_COLLAPSED | true, false | false | Start collapsed |
VITE_SIDEBAR_COLLAPSIBLE_STYLE | offcanvas, icon, none | icon | Collapse behavior |
VITE_ENABLE_SIDEBAR_TRIGGER | true, false | true | Show collapse button |
Feature Flags
VITE_ACCOUNT_MODE=hybridVITE_ENABLE_THEME_TOGGLE=trueVITE_ENABLE_PERSONAL_ACCOUNT_DELETION=falseVITE_ENABLE_PERSONAL_ACCOUNT_BILLING=falseVITE_ENABLE_TEAM_ACCOUNTS_CREATION=trueVITE_ENABLE_TEAM_ACCOUNTS_DELETION=falseVITE_ENABLE_TEAM_ACCOUNTS_BILLING=falseVITE_ENABLE_NOTIFICATIONS=trueVITE_REALTIME_NOTIFICATIONS=falseVITE_ENABLE_VERSION_UPDATER=falseVITE_LANGUAGE_PRIORITY=application| Variable | Default | Description |
|---|---|---|
VITE_ACCOUNT_MODE | hybrid | personal-only | organizations-only | hybrid. Single control for which account surfaces exist; the team-account flags below are derived from and gated by it. |
VITE_ENABLE_PERSONAL_ACCOUNT_DELETION | false | Users can delete accounts |
VITE_ENABLE_PERSONAL_ACCOUNT_BILLING | false | Personal subscription billing |
VITE_ENABLE_TEAM_ACCOUNTS_CREATION | true | Users can create teams |
VITE_ENABLE_TEAM_ACCOUNTS_DELETION | false | Users can delete teams |
VITE_ENABLE_TEAM_ACCOUNTS_BILLING | false | Team subscription billing |
VITE_ENABLE_NOTIFICATIONS | true | In-app notifications |
VITE_REALTIME_NOTIFICATIONS | false | Live notification updates |
VITE_ENABLE_VERSION_UPDATER | false | Check for updates |
VITE_LANGUAGE_PRIORITY | application | user or application |
Billing Configuration
Provider Selection
VITE_BILLING_PROVIDER=stripeOptions: stripe or lemon-squeezy
Stripe
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...STRIPE_SECRET_KEY=sk_test_...STRIPE_WEBHOOK_SECRET=whsec_...| Variable | Required | Description |
|---|---|---|
VITE_STRIPE_PUBLISHABLE_KEY | Yes (Stripe) | Publishable key |
STRIPE_SECRET_KEY | Yes (Stripe) | Secret key |
STRIPE_WEBHOOK_SECRET | Yes (Stripe) | Webhook signing secret |
Lemon Squeezy
LEMON_SQUEEZY_SECRET_KEY=your-secret-keyLEMON_SQUEEZY_STORE_ID=your-store-idLEMON_SQUEEZY_SIGNING_SECRET=your-signing-secret| Variable | Required | Description |
|---|---|---|
LEMON_SQUEEZY_SECRET_KEY | Yes (LS) | API secret key |
LEMON_SQUEEZY_STORE_ID | Yes (LS) | Store identifier |
LEMON_SQUEEZY_SIGNING_SECRET | Yes (LS) | Webhook signing secret |
Email Configuration
Provider Selection
MAILER_PROVIDER=nodemailerOptions: nodemailer or resend
Common Settings
EMAIL_SENDER="Your App <noreply@yourapp.com>"CONTACT_EMAIL=contact@yourapp.comResend
RESEND_API_KEY=re_...Nodemailer (SMTP)
EMAIL_HOST=smtp.provider.comEMAIL_PORT=587EMAIL_USER=your-usernameEMAIL_PASSWORD=your-passwordEMAIL_TLS=trueCMS Configuration
Provider Selection
CMS_CLIENT=keystaticOptions: keystatic or wordpress
Keystatic
VITE_KEYSTATIC_STORAGE_KIND=localVITE_KEYSTATIC_CONTENT_PATH=./contentKEYSTATIC_PATH_PREFIX=apps/webFor GitHub storage:
VITE_KEYSTATIC_STORAGE_KIND=githubVITE_KEYSTATIC_STORAGE_REPO=owner/repoKEYSTATIC_GITHUB_TOKEN=github_pat_...| Variable | Options | Description |
|---|---|---|
VITE_KEYSTATIC_STORAGE_KIND | local, cloud, github | Storage backend |
VITE_KEYSTATIC_CONTENT_PATH | Path | Content directory |
KEYSTATIC_PATH_PREFIX | Path | Monorepo prefix |
VITE_KEYSTATIC_STORAGE_REPO | owner/repo | GitHub repository |
KEYSTATIC_GITHUB_TOKEN | Token | GitHub access token |
WordPress
WORDPRESS_API_URL=https://your-site.com/wp-jsonSecurity Best Practices
- Never commit secrets: Use
.env.localfor sensitive values - Use CI/CD variables: Store production secrets in your deployment platform
- Rotate keys regularly: Especially after team member changes
- Validate in production: The kit validates configuration at build time
Common Pitfalls
- HTTP in production:
VITE_SITE_URLmust usehttps://in production builds. - Same theme colors:
VITE_THEME_COLORandVITE_THEME_COLOR_DARKmust be different. - Missing Supabase keys: The app won't start without valid Supabase credentials.
- Forgetting to restart: After changing environment variables, you may need to restart the development server.
- Wrong file for secrets: Put secrets in
.env.local(git-ignored), not.env(committed).
Related Topics
- Application Configuration - Core app settings
- Authentication Configuration - Auth setup
- Feature Flags - Toggle features
- Going to Production - Deployment checklist