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.
Warning
This project is just getting started, so things are gonna change a lot. Updates will roll out often, and we’re totally open to feedback—hit us up with your thoughts!
- 🎯 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
- 🔒 Type Safety: Catch errors early with full type inference and validation
# 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
- Add the module to your
nuxt.config.ts
:
// Basic usage with plain configuration
export default defineNuxtConfig({
modules: ['nuxt-feature-flags'],
featureFlags: {
flags: {
newDashboard: false,
experimentalFeature: true
}
}
})
// Advanced usage with context-based flag rules
// feature-flags.config.ts
import { defineFeatureFlags } from '#feature-flags/handler'
export default defineFeatureFlags((context) => {
return {
isAdmin: context?.user?.role === 'admin',
newDashboard: true,
experimentalFeature: process.env.NODE_ENV === 'development',
betaFeature: context?.user?.isBetaTester ?? false,
}
})
- Use in your Vue components:
<script setup>
const { isEnabled } = useFeatureFlags()
</script>
<template>
<div>
<NewDashboard v-if="isEnabled('newDashboard')" />
</div>
</template>
- Use in your server routes:
// server/api/dashboard.ts
export default defineEventHandler(async (event) => {
const { isEnabled } = getFeatureFlags(event)
if (!isEnabled('newDashboard')) {
throw createError({
statusCode: 404,
message: 'Dashboard not available'
})
}
return {
stats: {
users: 100,
revenue: 50000
}
}
})
const {
flags, // Reactive flags object
isEnabled, // (flagName: string) => boolean
} = useFeatureFlags()
// Check if a flag is enabled
if (isEnabled('newFeature')) {
// Feature is enabled
}
const {
flags, // Flags object
isEnabled, // (flagName: string) => boolean
} = await getFeatureFlags(event)
// Check if a flag is enabled
if (isEnabled('newFeature')) {
// Feature is enabled
}
export default defineNuxtConfig({
featureFlags: {
flags: {
promoBanner: true,
betaFeature: false,
newDashboard: false
}
}
})
// nuxt.config.ts
export default defineNuxtConfig({
featureFlags: {
config: './feature-flags.config.ts',
}
})
// feature-flags.config.ts
import { defineFeatureFlags } from '#feature-flags/handler'
export default defineFeatureFlags(() => {
isAdmin: false,
newDashboard: true,
experimentalFeature: true,
promoBanner: false,
betaFeature: false,
})
// 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,
}
})
- Clone this repository
- Install dependencies using
npm install
- Start development server using
npm run dev
- Make your changes
- Submit a pull request
Thanks goes to these wonderful people (emoji key):
Roberth González 💻 |
Eugen Istoc 💻 |
Daniel Roe 📖 |
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT License © 2025 Roberth González