Lightweight, backend-agnostic feature flags plugin for Vue 3 — boolean and multivariate flags, contextual rules, live updates, and a DevTools overlay.

A new feature's code is often ready before marketing, QA, or the product manager are ready to turn it on — a feature flag separates the moment of deployment from the moment a feature actually becomes visible to users.
First 5% of users see it, then 25%, then everyone — if something goes wrong, rolling back is easier than cleaning up after a full release.
Some users see the old checkout button, others see the new one, and conversion is compared based on actual usage, not on which version the team happens to prefer.
One set of features is on to check a new onboarding flow, another is on to test regression against old behavior. Instead of clicking through a dozen toggles by hand, a whole set is saved and switched on with one click.
Something breaks overnight with a recently shipped feature, and nobody with server access is around — the flag can be flipped off remotely, and it takes effect immediately, without rebuilding or redeploying anything.

Control features with simple boolean flags or string variants for A/B tests and phased rollouts. Static flags, async backend loading, periodic polling, and a priority chain (URL → runtime → rules → loader → static → defaultValue) give you full control over the logic.

Reactive rules based on any conditions (time, cookies, prefers-color-scheme) auto‑update flags. URL parameters let you override flags without a page reload, and persisted flags survive in localStorage. All work together, providing flexibility at every level.

Group flags for mass enable/disable. Set dependencies so one flag auto‑disables when another is off. Save named override sets as profiles for quick switching between scenarios (demo, QA).

Use the declarative <Feature> component with default/fallback/loading slots, the v-feature directive for v‑show‑style toggling, and the useFeature composable for reactive logic. Multivariate flags are supported via <FeatureVariant> and useFeatureVariant. All tools are type‑safe.

A built‑in floating DevTools panel for inspecting and controlling flags, a CLI for analyzing flags in code (list/check/stale), adapters for LaunchDarkly, Unleash, and Flagsmith. A Nuxt module with SSR hydration, a Storybook decorator, and a Vite plugin to strip DevTools in production.

Give a flag a { value, rollout } object and it turns on only for that percentage of users, deterministically bucketed by a hash of their id rather than randomly. Schedule flags to activate on specific future dates, and metadata plus an expiry date help track down stale toggles.
Rules are plain reactive functions — dark mode from the system preference, a chat widget from time of day, developer access from a cookie. Still overridable by a URL param or setFlag().
import { FeatureToggles } from 'vue-feature-toggles'
app.use(FeatureToggles, {
rules: {
darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
liveChatWidget: () => {
const h = new Date().getHours()
return h >= 9 && h < 18
},
devFeatures: () => document.cookie.includes('internal=1'),
},
})
// Rules are reactive functions, re-evaluated whenever their inputs change —
// still overridable by a URL param or setFlag() at runtime.checkoutFlow holds a string variant instead of a boolean — <FeatureVariant> renders the right slot on its own, and switching via ?feature:checkoutFlow=v2 works without a reload.
<script setup lang="ts">
import { useFeatureVariant } from 'vue-feature-toggles'
const variant = useFeatureVariant('checkoutFlow') // Ref<string>
</script>
<template>
<FeatureVariant name="checkoutFlow">
<template #v1><CheckoutV1 /></template>
<template #v2><CheckoutV2 /></template>
<template #fallback><CheckoutLegacy /></template>
</FeatureVariant>
</template>
<!-- URL overrides work identically: ?feature:checkoutFlow=v2 --> The server pushes { betaSearch: true } over SSE or WebSocket, and every component using that flag re-renders instantly — no polling required.
import { FeatureToggles } from 'vue-feature-toggles'
app.use(FeatureToggles, {
loader: async () => fetch('/api/flags').then((r) => r.json()),
liveUpdates: { type: 'sse', url: '/api/flags/stream' },
})
// The server pushes { "betaSearch": true }, and every component using that
// flag re-renders instantly — no polling, no page reload.