Skip to content

Context-Aware Configuration

Context-aware configuration allows you to create dynamic feature flags that evaluate differently based on request-specific information.

Context Structure

The context parameter provides request-specific information:

ts
interface VariantContext {
  // User identification
  userId?: string
  sessionId?: string
  ipAddress?: string
  
  // User information
  user?: {
    id?: string
    role?: string
    isBetaTester?: boolean
    [key: string]: any
  }
  
  // Device information
  device?: {
    isMobile?: boolean
    [key: string]: any
  }
  
  // Additional custom context
  [key: string]: any
}

Populating Context

Context is automatically extracted from H3 events on the server. Enrich it using server middleware:

ts
// server/middleware/user-context.ts
export default defineEventHandler(async (event) => {
  // Get authenticated user
  const user = await getUserFromSession(event)
  
  if (user) {
    event.context.user = {
      id: user.id,
      role: user.role,
      isBetaTester: user.betaTester,
      subscriptionTier: user.subscription
    }
  }
  
  // Detect device information
  const userAgent = getHeader(event, 'user-agent') || ''
  event.context.device = {
    isMobile: /mobile/i.test(userAgent),
    isTablet: /tablet/i.test(userAgent)
  }
})

Usage Examples

Role-Based Flags

ts
// feature-flags.config.ts
export default defineFeatureFlags((context) => {
  return {
    // Admin-only features
    adminPanel: context?.user?.role === 'admin',
    advancedSettings: context?.user?.role === 'admin' || context?.user?.role === 'moderator',
    
    // Role-based feature variants
    dashboard: {
      enabled: true,
      value: context?.user?.role === 'admin' ? 'advanced' : 'basic'
    }
  }
})

Environment-Based Flags

ts
export default defineFeatureFlags((context) => {
  const isDev = process.env.NODE_ENV === 'development'
  const isProd = process.env.NODE_ENV === 'production'
  
  return {
    // Development-only features
    devTools: isDev,
    debugPanel: isDev,
    
    // Production features with gradual rollout
    newCheckout: {
      enabled: isProd,
      variants: [
        { name: 'old', weight: 80, value: false },
        { name: 'new', weight: 20, value: true }
      ]
    }
  }
})

User Status-Based Flags

ts
export default defineFeatureFlags((context) => {
  const user = context?.user
  
  return {
    // Beta tester features
    betaFeatures: user?.isBetaTester ?? false,
    
    // Subscription-based features
    premiumFeatures: user?.subscriptionTier === 'premium',
    proTools: ['pro', 'premium', 'enterprise'].includes(user?.subscriptionTier),
    
    // Account age-based rollout
    newUserExperience: {
      enabled: true,
      value: (user?.accountAge || 0) < 30
    }
  }
})

Device-Based Flags

ts
export default defineFeatureFlags((context) => {
  const device = context?.device
  
  return {
    // Mobile-specific features
    mobileOptimizedUI: device?.isMobile ?? false,
    touchGestures: device?.isMobile || device?.isTablet,
    
    // Desktop-only features
    keyboardShortcuts: !device?.isMobile,
    
    // Responsive feature variants
    imageQuality: {
      enabled: true,
      value: device?.isMobile ? 'medium' : 'high'
    }
  }
})

Fallback Behavior

When context is unavailable, flags gracefully fall back to default values:

ts
export default defineFeatureFlags((context) => {
  return {
    // Using nullish coalescing for safe defaults
    adminPanel: context?.user?.role === 'admin',  // false if undefined
    
    // Explicit fallback values
    betaFeatures: context?.user?.isBetaTester ?? false,
    maxItems: context?.user?.preferences?.itemsPerPage ?? 20,
    
    // Fallback chains
    userId: context?.user?.id || context?.userId || 'anonymous'
  }
})

Best Practices

  • Always use optional chaining (?.) when accessing context properties
  • Provide sensible defaults with nullish coalescing (??)
  • Test your flags with and without context
  • Document which flags require context and their fallback behavior
  • Populate context.user.id in middleware for consistent variant assignment

Released under the MIT License.