--- status: "published" label: "Feature Flags" title: "Feature Flags Configuration in the Next.js Supabase SaaS Kit" description: "Enable or disable team accounts, billing, notifications, and theme toggling in the Next.js Supabase SaaS Kit using feature flags." order: 4 --- The feature flags configuration at `apps/web/config/feature-flags.config.ts` controls which features are enabled in your application. Toggle team accounts, billing, notifications, and more using environment variables. {% alert type="default" title="Feature Flags vs Configuration" %} Feature flags control whether functionality is available to users. Use them to ship different product tiers, run A/B tests, or disable features during maintenance. Unlike configuration, feature flags are meant to change at runtime or between deployments. {% /alert %} {% alert type="warning" title="Defaults Note" %} The "Default" column shows what the code uses if the environment variable is not set. The kit's `.env` file ships with different values to demonstrate features. Check your `.env` file for the actual starting values. {% /alert %} ## Available Feature Flags | Flag | Environment Variable | Default | Description | |------|---------------------|---------|-------------| | Theme Toggle | `NEXT_PUBLIC_ENABLE_THEME_TOGGLE` | `true` | Allow users to switch themes | | Account Deletion | `NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION` | `false` | Users can delete their accounts | | Team Accounts | `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS` | `true` | Enable team/organization features | | Team Creation | `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION` | `true` | Users can create new teams | | Team Deletion | `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_DELETION` | `false` | Users can delete their teams | | Personal Billing | `NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING` | `false` | Billing for personal accounts | | Team Billing | `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING` | `false` | Billing for team accounts | | Notifications | `NEXT_PUBLIC_ENABLE_NOTIFICATIONS` | `true` | In-app notification system | | Realtime Notifications | `NEXT_PUBLIC_REALTIME_NOTIFICATIONS` | `false` | Live notification updates | | Version Updater | `NEXT_PUBLIC_ENABLE_VERSION_UPDATER` | `false` | Check for app updates | | Teams Only | `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY` | `false` | Skip personal accounts, use teams only | | Language Priority | `NEXT_PUBLIC_LANGUAGE_PRIORITY` | `application` | User vs app language preference | ## Common Configurations ### B2C SaaS (Personal Accounts Only) For consumer applications where each user has their own account and subscription: ```bash NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS=false NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING=true NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION=true ``` ### B2B SaaS (Team Accounts Only) For business applications where organizations subscribe and manage team members. Enable `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY` to skip personal accounts entirely: ```bash NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_DELETION=true NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING=false ``` When `NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_ONLY=true`: - Users are automatically redirected away from personal account routes to their team workspace - The personal account section in the sidebar/workspace switcher is hidden - After sign-in, users land on their team dashboard instead of a personal home page - The last selected team is remembered in a cookie so returning users go straight to their team This is the recommended approach for B2B apps. It removes the personal account layer entirely so users only interact with team workspaces. ### Hybrid Model (Both Personal and Team) For applications supporting both individual users and teams (uncommon): ```bash NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS=true NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING=true ``` ### Managed Onboarding (No Self-Service Team Creation) For applications where you create teams on behalf of customers: ```bash NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS=true NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION=false NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING=true ``` ## Decision Matrix Use this matrix to decide which flags to enable: | Use Case | Theme | Teams | Team Creation | Personal Billing | Team Billing | Deletion | |----------|-------|-------|---------------|------------------|--------------|----------| | B2C Consumer App | Yes | No | - | Yes | - | Yes | | B2B Team SaaS | Optional | Yes | Yes | No | Yes | Optional | | Enterprise SaaS | Optional | Yes | No | No | Yes | No | | Freemium Personal | Yes | No | - | Yes | - | Yes | | Marketplace | Optional | Yes | Yes | Yes | No | Yes | ## How It Works The configuration file parses environment variables with sensible defaults: ```typescript const featuresFlagConfig = FeatureFlagsSchema.parse({ enableThemeToggle: getBoolean( process.env.NEXT_PUBLIC_ENABLE_THEME_TOGGLE, true, ), enableAccountDeletion: getBoolean( process.env.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_DELETION, false, ), enableTeamDeletion: getBoolean( process.env.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_DELETION, false, ), enableTeamAccounts: getBoolean( process.env.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS, true, ), enableTeamCreation: getBoolean( process.env.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION, true, ), enablePersonalAccountBilling: getBoolean( process.env.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING, false, ), enableTeamAccountBilling: getBoolean( process.env.NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING, false, ), languagePriority: process.env.NEXT_PUBLIC_LANGUAGE_PRIORITY, enableNotifications: getBoolean( process.env.NEXT_PUBLIC_ENABLE_NOTIFICATIONS, true, ), realtimeNotifications: getBoolean( process.env.NEXT_PUBLIC_REALTIME_NOTIFICATIONS, false, ), enableVersionUpdater: getBoolean( process.env.NEXT_PUBLIC_ENABLE_VERSION_UPDATER, false, ), }); ``` ## Using Feature Flags in Code ### In Server Components ```typescript import featureFlagsConfig from '~/config/feature-flags.config'; export default function SettingsPage() { return (