Module Configuration
Configuration Options
The module accepts the following options in nuxt.config.ts:
interface FeatureFlagsConfig {
flags?: FlagDefinition // Inline feature flags object
config?: string // Path to configuration file
}
type FlagDefinition = Record<string, boolean | FlagConfig>
interface FlagConfig {
enabled: boolean
value?: any
variants?: Array<{
name: string
weight: number
value?: any
}>
}Configuration Methods
Method 1: Inline Configuration
Best for simple projects with a small number of static flags:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-feature-flags'],
featureFlags: {
flags: {
newDashboard: false,
experimentalFeature: true,
darkMode: true
}
}
})Pros:
- Simple and straightforward
- No additional files needed
- Good for quick prototypes
Cons:
- Limited to static flags
- Can clutter
nuxt.config.ts - No context-aware evaluation
When to use: Quick prototypes, simple feature toggles, or when you have fewer than 10 flags.
Method 2: Configuration File
Best for most projects. Keep your flags organized in a dedicated configuration file:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-feature-flags'],
featureFlags: {
config: './feature-flags.config.ts' // Relative to project root
}
})
// feature-flags.config.ts
import { defineFeatureFlags } from '#feature-flags/handler'
export default defineFeatureFlags(() => ({
newDashboard: true,
experimentalFeature: process.env.NODE_ENV === 'development',
betaFeature: false,
// A/B test with variants
buttonDesign: {
enabled: true,
value: 'default',
variants: [
{ name: 'control', weight: 50, value: 'original' },
{ name: 'treatment', weight: 50, value: 'new-design' }
]
}
}))Pros:
- Clean separation of concerns
- Supports environment-based flags
- Can use TypeScript
- Better organization
Cons:
- Requires additional file
- Slightly more setup
When to use: Production applications, when you need environment-based flags, or when managing multiple flags.
Configuration file location: You can place your config file anywhere in your project:
./feature-flags.config.ts(project root)./config/feature-flags.ts./flags.config.ts
Just update the config path in nuxt.config.ts to match your chosen location.
Method 3: Context-Aware Configuration
Best for dynamic flags that depend on user attributes, request context, or runtime conditions:
// feature-flags.config.ts
import { defineFeatureFlags } from '#feature-flags/handler'
export default defineFeatureFlags((context) => {
return {
// User role-based flag
isAdmin: context?.user?.role === 'admin',
// Environment-based flag
devTools: process.env.NODE_ENV === 'development',
// User status-based flag
betaFeature: context?.user?.isBetaTester ?? false,
// Device-based flag
mobileFeature: context?.device?.isMobile ?? false,
// Gradual rollout (30% get new feature)
newCheckout: {
enabled: true,
variants: [
{ name: 'old', weight: 70, value: false },
{ name: 'new', weight: 30, value: true }
]
}
}
})Pros:
- Dynamic evaluation per request
- User-specific features
- Device-aware flags
- Perfect for A/B testing
Cons:
- Requires context population
- More complex setup
- Needs middleware for user data
When to use: Personalized features, role-based access, A/B testing, or when flags need to evaluate differently per user/request.
Flag Types
Simple Flags
Simple boolean or value flags:
{
newDashboard: true, // Boolean
maxItems: 10, // Number
theme: 'dark', // String
deprecatedFeature: null // Null
}Flag Config Objects
Advanced flags with variants for A/B testing:
{
experiment: {
enabled: true, // Master switch
value: 'default', // Default value
variants: [
{ name: 'control', weight: 50, value: 'A' },
{ name: 'treatment', weight: 50, value: 'B' }
]
}
}Environment Variables
Use environment variables for environment-specific configuration:
// feature-flags.config.ts
export default defineFeatureFlags(() => {
const isDev = process.env.NODE_ENV === 'development'
const isProd = process.env.NODE_ENV === 'production'
return {
devTools: isDev,
analytics: isProd,
experimentalFeatures: isDev || process.env.ENABLE_EXPERIMENTAL === 'true'
}
})Best Practices
1. Use Descriptive Names
// ✅ Good
{
newUserDashboard: true,
betaSearchAlgorithm: false,
improvedCheckout: true
}
// ❌ Avoid
{
feature1: true,
newStuff: false,
test: true
}2. Organize by Feature Area
export default defineFeatureFlags(() => ({
// Authentication features
authSocialLogin: true,
authTwoFactor: false,
// UI features
uiDarkMode: true,
uiCompactView: false,
// Experimental features
experimentNewSearch: { enabled: true, variants: [...] }
}))3. Document Your Flags
/**
* Flag: newCheckoutFlow
* Owner: @payments-team
* Created: 2024-01-15
* Purpose: Gradual rollout of redesigned checkout
* Target: 100% by 2024-02-15
* Removal: 2024-03-01
*/
newCheckoutFlow: {
enabled: true,
variants: [...]
}4. Clean Up Old Flags
Remove flags after features are fully rolled out:
// Before: Feature behind flag
if (isEnabled('newFeature')) {
return <NewComponent />
}
// After: Flag removed, feature is default
return <NewComponent />5. Use Fallback Values
Always provide sensible defaults:
export default defineFeatureFlags((context) => ({
betaFeatures: context?.user?.isBetaTester ?? false, // Defaults to false
maxItems: context?.user?.preferences?.itemsPerPage ?? 20,
theme: context?.user?.preferences?.theme || 'light'
}))Next Steps
- Learn about Context-Aware Configuration
- Explore Variants & A/B Testing
- Check the API Reference
- Review Best Practices