Nuxt Feature Flags 🚩 ​
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 with built-in variant support.
Features ​
- 🎯 Context-aware evaluation: Evaluate flags based on request context (user roles, geo-location, device type, etc.)
- 🛠TypeScript Ready: Full TypeScript support with type-safe flag definitions and autocomplete
- 🧩 Nuxt 3 Integration: Seamless integration with auto-imports and runtime config
- 🎯 Static & Dynamic Flags: Support for both simple boolean flags and dynamic evaluation
- 🔀 A/B/n Testing: Built-in support for feature variants with configurable distribution
- 🎲 Persistent Assignment: Users consistently get the same variant across sessions
- 📊 Validation & Linting: Built-in validation for flag configuration and usage
- 🔒 Type Safety: Catch errors early with full type inference and validation
Quick Setup ​
- Add the module to your Nuxt project:
bash
# Using npx
npx nuxi module add nuxt-feature-flags
# Using npm
npm install nuxt-feature-flags
# Using yarn
yarn add nuxt-feature-flags
# Using pnpm
pnpm add nuxt-feature-flags- Configure your feature flags:
ts
// Method 1: Inline Configuration (Simplest)
export default defineNuxtConfig({
modules: ['nuxt-feature-flags'],
featureFlags: {
flags: {
newDashboard: false,
experimentalFeature: true,
darkMode: true
}
}
})
// Method 2: Configuration File (Recommended)
// 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' }
]
}
}))
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-feature-flags'],
featureFlags: {
config: './feature-flags.config.ts'
}
})- Use in your Vue components:
vue
<script setup>
const { isEnabled, getVariant, getValue } = useFeatureFlags()
</script>
<template>
<div>
<!-- Simple feature flag -->
<NewDashboard v-if="isEnabled('newDashboard')" />
<!-- A/B test with variants -->
<div v-feature="'buttonDesign:control'">
<button class="original-style">Click me</button>
</div>
<div v-feature="'buttonDesign:treatment'">
<button class="new-style">Click me</button>
</div>
<!-- Check specific variant programmatically -->
<div v-if="getVariant('buttonDesign') === 'treatment'">
You're seeing the new design! Value: {{ getValue('buttonDesign') }}
</div>
</div>
</template>- Use in your server routes:
ts
// server/api/dashboard.ts
export default defineEventHandler(async (event) => {
const { isEnabled, getVariant, getValue } = getFeatureFlags(event)
if (!isEnabled('newDashboard')) {
throw createError({
statusCode: 404,
message: 'Dashboard not available'
})
}
// Check if user is in new checkout variant
const checkoutVersion = getVariant('newCheckout')
return {
stats: {
users: 100,
revenue: 50000
},
checkoutVersion,
useNewFeatures: getValue('newCheckout')
}
})