Skip to content

A powerful, type-safe feature flag module for Nuxt 3 that enables both static and dynamic feature flag evaluation with server-side support. Perfect for A/B testing, gradual rollouts, and feature management.

License

Notifications You must be signed in to change notification settings

roberthgnz/nuxt-feature-flags

Repository files navigation

nuxt-feature-flags

npm version npm downloads License Nuxt

Nuxt Feature Flags 🚩

A powerful, type-safe feature flag module for Nuxt 3 with A/B testing and variant support.

✨ Features

  • 🎯 Context-aware evaluation - Evaluate flags based on user, device, environment
  • πŸ›  TypeScript Ready - Full type safety with autocomplete
  • 🧩 Nuxt 3 Integration - Seamless integration with auto-imports
  • πŸ”€ A/B/n Testing - Built-in variant support with persistent assignment
  • οΏ½ Validateion - Built-in validation for flag configuration
  • πŸ”’ Type Safety - Catch errors early with full type inference

πŸ“¦ Installation

npx nuxi module add nuxt-feature-flags

πŸš€ Quick Start

1. Add to your Nuxt config

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-feature-flags']
})

2. Configure your flags

// feature-flags.config.ts
import { defineFeatureFlags } from '#feature-flags/handler'

export default defineFeatureFlags(() => ({
  newDashboard: true,
  darkMode: false,
  
  // A/B test with variants
  buttonDesign: {
    enabled: true,
    variants: [
      { name: 'control', weight: 50, value: 'blue' },
      { name: 'treatment', weight: 50, value: 'red' }
    ]
  }
}))
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-feature-flags'],
  featureFlags: {
    config: './feature-flags.config.ts'
  }
})

3. Use in your app

In components:

<script setup>
const { isEnabled, getValue, getVariant } = useFeatureFlags()
</script>

<template>
  <div>
    <!-- Simple flag check -->
    <NewDashboard v-if="isEnabled('newDashboard')" />
    
    <!-- Using directive -->
    <div v-feature="'darkMode'">Dark mode content</div>
    
    <!-- A/B test variants -->
    <button :class="`btn-${getValue('buttonDesign')}`">
      Click me
    </button>
  </div>
</template>

In server routes:

// server/api/data.ts
export default defineEventHandler((event) => {
  const { isEnabled, getValue } = getFeatureFlags(event)
  
  if (!isEnabled('newDashboard')) {
    throw createError({ statusCode: 404 })
  }
  
  return { data: 'Dashboard data' }
})

🎯 Context-Aware Flags

Create dynamic flags based on user, device, or environment:

// feature-flags.config.ts
export default defineFeatureFlags((context) => ({
  // Role-based
  adminPanel: context?.user?.role === 'admin',
  
  // Environment-based
  devTools: process.env.NODE_ENV === 'development',
  
  // Device-based
  mobileUI: context?.device?.isMobile ?? false,
  
  // Gradual rollout (20% of users)
  newFeature: {
    enabled: true,
    variants: [
      { name: 'old', weight: 80, value: false },
      { name: 'new', weight: 20, value: true }
    ]
  }
}))

Populate context in server middleware:

// server/middleware/user-context.ts
export default defineEventHandler(async (event) => {
  const user = await getUserFromSession(event)
  
  if (user) {
    event.context.user = {
      id: user.id,
      role: user.role
    }
  }
})

πŸ“– API Reference

Client-Side

const { 
  flags,              // Ref<ResolvedFlags>
  isEnabled,          // (flag: string, variant?: string) => boolean
  getVariant,         // (flag: string) => string | undefined
  getValue,           // (flag: string) => any
  getFlag,            // (flag: string) => ResolvedFlag | undefined
  fetch               // () => Promise<void>
} = useFeatureFlags()

Server-Side

const { 
  flags,              // ResolvedFlags
  isEnabled,          // (flag: string, variant?: string) => boolean
  getVariant,         // (flag: string) => string | undefined
  getValue,           // (flag: string) => any
  getFlag             // (flag: string) => ResolvedFlag | undefined
} = getFeatureFlags(event)

Template Directive

<template>
  <!-- Show if flag is enabled -->
  <div v-feature="'myFlag'">Content</div>
  
  <!-- Show for specific variant -->
  <div v-feature="'myFlag:variantA'">Variant A content</div>
</template>

βœ… Validation

Validate flags at build time:

// scripts/validate-flags.ts
import { validateFeatureFlags } from 'nuxt-feature-flags/build'

const errors = await validateFeatureFlags({
  configPath: './feature-flags.config.ts',
  srcPatterns: ['**/*.vue', '**/*.ts'],
  failOnErrors: true
})

πŸ“š Documentation

For detailed documentation, visit nuxt-feature-flags-docs.vercel.app

🀝 Contributing

Contributions are welcome! Please read our contributing guide.

πŸ“„ License

MIT License Β© 2024

About

A powerful, type-safe feature flag module for Nuxt 3 that enables both static and dynamic feature flag evaluation with server-side support. Perfect for A/B testing, gradual rollouts, and feature management.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 5