Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
261 lines
9.6 KiB
Plaintext
261 lines
9.6 KiB
Plaintext
---
|
|
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 (
|
|
<div>
|
|
{featureFlagsConfig.enableTeamAccounts && (
|
|
<TeamAccountsSection />
|
|
)}
|
|
{featureFlagsConfig.enableAccountDeletion && (
|
|
<DeleteAccountButton />
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
### In Client Components
|
|
|
|
```tsx
|
|
'use client';
|
|
|
|
import featureFlagsConfig from '~/config/feature-flags.config';
|
|
|
|
export function ThemeToggle() {
|
|
if (!featureFlagsConfig.enableThemeToggle) {
|
|
return null;
|
|
}
|
|
|
|
return <ThemeSwitch />;
|
|
}
|
|
```
|
|
|
|
### Conditional Navigation
|
|
|
|
The navigation configuration files already use feature flags:
|
|
|
|
```typescript
|
|
// From personal-account-navigation.config.tsx
|
|
featureFlagsConfig.enablePersonalAccountBilling
|
|
? {
|
|
label: 'common.routes.billing',
|
|
path: pathsConfig.app.personalAccountBilling,
|
|
Icon: <CreditCard className={iconClasses} />,
|
|
}
|
|
: undefined,
|
|
```
|
|
|
|
## Feature Flag Details
|
|
|
|
### Theme Toggle
|
|
|
|
Controls whether users can switch between light and dark themes. When disabled, the app uses `NEXT_PUBLIC_DEFAULT_THEME_MODE` exclusively.
|
|
|
|
### Account Deletion
|
|
|
|
Allows users to permanently delete their personal accounts. Disabled by default to prevent accidental data loss. Consider enabling for GDPR compliance.
|
|
|
|
### Team Accounts
|
|
|
|
Master switch for all team functionality. When disabled, the application operates in personal-account-only mode. Disabling this also hides team-related navigation and features.
|
|
|
|
### Team Creation
|
|
|
|
Controls whether users can create new teams. Set to `false` for enterprise scenarios where you provision teams manually.
|
|
|
|
### Team Deletion
|
|
|
|
Allows team owners to delete their teams. Disabled by default to prevent accidental data loss.
|
|
|
|
### Personal vs Team Billing
|
|
|
|
Choose one based on your business model:
|
|
|
|
- **Personal billing**: Each user subscribes individually (B2C)
|
|
- **Team billing**: Organizations subscribe and add team members (B2B)
|
|
|
|
Enabling both is possible but uncommon. Most SaaS applications use one model.
|
|
|
|
### Notifications
|
|
|
|
Enables the in-app notification system. When combined with `realtimeNotifications`, notifications appear instantly via Supabase Realtime.
|
|
|
|
### Language Priority
|
|
|
|
Controls language selection behavior:
|
|
|
|
- `application`: Use the app's default locale
|
|
- `user`: Respect the user's browser language preference
|
|
|
|
### Version Updater
|
|
|
|
When enabled, the app checks for updates and notifies users. Useful for deployed applications that receive frequent updates.
|
|
|
|
## Common Pitfalls
|
|
|
|
1. **Enabling both billing modes**: While technically possible, enabling both personal and team billing may create confusing user experience (unless your business model is a hybrid of both). Choose one model.
|
|
2. **Disabling teams after launch**: If you've collected team data and then disable teams, users lose access. Plan your model before launch.
|
|
3. **Forgetting deletion flows**: If you enable deletion, ensure you also handle cascading data deletion and GDPR compliance.
|
|
4. **Realtime without base notifications**: `realtimeNotifications` requires `enableNotifications` to be true. The realtime flag adds live updates, not the notification system itself.
|
|
|
|
## Related Topics
|
|
|
|
- [Application Configuration](/docs/next-supabase-turbo/configuration/application-configuration) - Core app settings
|
|
- [Environment Variables](/docs/next-supabase-turbo/configuration/environment-variables) - Complete variable reference
|
|
- [Navigation Configuration](/docs/next-supabase-turbo/configuration/personal-account-sidebar-configuration) - Sidebar customization
|