Skip to content

Module Configuration

Configuration Options

The module accepts the following options in nuxt.config.ts:

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:

ts
// 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:

ts
// 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:

ts
// 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:

ts
{
  newDashboard: true,           // Boolean
  maxItems: 10,                 // Number
  theme: 'dark',                // String
  deprecatedFeature: null       // Null
}

Flag Config Objects

Advanced flags with variants for A/B testing:

ts
{
  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:

ts
// 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

ts
// ✅ Good
{
  newUserDashboard: true,
  betaSearchAlgorithm: false,
  improvedCheckout: true
}

// ❌ Avoid
{
  feature1: true,
  newStuff: false,
  test: true
}

2. Organize by Feature Area

ts
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

ts
/**
 * 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:

ts
// 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:

ts
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

Released under the MIT License.