Skip to content

Nuxt Module ​

ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['vue-feature-toggles/nuxt'],

  featureToggles: {
    flags: { newDashboard: true, betaSearch: false },
    urlOverrides: true,
    urlPrefix: 'feature',
    defaultValue: false,
    reloadInterval: 0,
    userId: currentUser.id,
    schedule: { holidayBanner: { from: '2025-12-01', to: '2025-12-31' } },
    variables: { newCheckout: { maxItems: 5 } },
    meta: { newDashboard: { owner: 'alice', addedAt: '2025-03-01' } },
    expiry: { betaBanner: '2025-06-01' },
    groups: { beta: ['betaSearch'] },
    dependencies: { aiSuggestions: ['newSearch'] },
    liveUpdates: { type: 'sse', url: '/api/flags/stream' },
    configFile: '~/feature-toggles.config.ts', // optional, see below
  },
})
  • <Feature>, <FeatureVariant>, and v-feature are registered globally
  • useFeature, useFeatureVariant, and useFeatureProvider are auto-imported — no explicit import needed
  • SSR hydration via nuxtApp.payload is handled automatically — no ssrState config needed
  • $featureToggles is injected into nuxtApp
ts
// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
  const { $featureToggles } = nuxtApp
  console.log($featureToggles.flags.value)
})

All options accepted by the Vue plugin work in nuxt.config.ts except loader and rules — see below.

Custom loader & rules with Nuxt ​

loader and rules are functions and cannot be serialized into nuxt.config.ts (Nuxt's public runtime config is JSON-serialized to the client) — the module's own TypeScript type deliberately excludes both from featureToggles, the same way it excludes ssrState. Point the module at a separate file instead, via the configFile option:

ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['vue-feature-toggles/nuxt'],
  featureToggles: {
    // ...other options
    configFile: '~/feature-toggles.config.ts',
  },
})
ts
// feature-toggles.config.ts
export default {
  loader: async () => {
    return $fetch('/api/flags')
  },
  rules: {
    darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
  },
}

The module resolves configFile into a generated virtual module that its own runtime plugin imports directly, so loader/rules stay real functions and never round-trip through runtimeConfig.

If you'd rather bypass the module's config entirely, you can still register the plugin yourself:

ts
// plugins/feature-toggles.ts
import { FeatureToggles } from 'vue-feature-toggles'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(FeatureToggles, {
    loader: async () => {
      return $fetch('/api/flags')
    },
    rules: {
      darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
    },
    urlOverrides: true,
  })
})