Component, Directive & Composables
Initialization options
ts
app.use(FeatureToggles, {
// Static flag values (boolean or variant string)
flags: { newDashboard: true, checkoutFlow: 'v2' },
// Async loader — fetches flags from a backend
loader: async () => {
const res = await fetch('/api/feature-flags')
return res.json()
},
// Poll interval for the loader in ms (default: 0 = disabled)
reloadInterval: 60_000,
// Allow ?feature:flagName=true in the URL (default: true in dev, false in prod)
urlOverrides: true,
// URL param prefix (default: 'feature')
urlPrefix: 'feature',
// Value returned for unknown flags (default: false)
defaultValue: false,
// Variables scoped to a flag
variables: {
newCheckout: { maxItems: 5, theme: 'dark' },
},
// Named flag groups
groups: {
beta: ['betaSearch', 'newDashboard'],
maintenance: ['maintenanceMode', 'readOnlyBanner'],
},
// Dependency enforcement: if a required flag is off, the dependent is forced off too
dependencies: {
aiSuggestions: ['newSearch'],
},
// Contextual rules — evaluated reactively, priority below setFlag/URL
rules: {
darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
},
// Flag metadata for DevTools and CLI
meta: {
newDashboard: {
description: 'New UI',
owner: 'alice',
addedAt: '2025-03-01',
ticket: 'PROJ-42',
},
},
// Automatic expiry dates — after this date the flag is treated as expired
expiry: {
christmasBanner: '2025-01-10',
},
// Live updates from the server (SSE or WebSocket)
liveUpdates: {
type: 'sse',
url: '/api/flags/stream',
},
// Server-side flag snapshot to prevent hydration mismatch
ssrState: window.__FEATURE_FLAGS__,
})<Feature> component
vue
<!-- Basic -->
<Feature name="newDashboard">
<NewDashboard />
</Feature>
<!-- Fallback slot -->
<Feature name="betaSearch">
<template #default><BetaSearchBar /></template>
<template #fallback><LegacySearchBar /></template>
</Feature>
<!-- Fallback prop -->
<Feature name="betaSearch" fallback="Feature is under development">
<BetaSearchBar />
</Feature>
<!-- Inverted — show when flag is off -->
<Feature name="maintenanceMode" :inverted="true">
<MainContent />
</Feature>
<!-- Wrap in an HTML element -->
<Feature name="newDashboard" tag="section">
<NewDashboard />
</Feature>
<!-- Loading state while loader runs -->
<Feature name="loaderFlag">
<template #loading><Spinner /></template>
<template #default><NewFeature /></template>
<template #fallback><OldFeature /></template>
</Feature>
<!-- Group — show when ALL flags in the group are enabled -->
<Feature group="beta">
<BetaLabel />
</Feature>Props
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Flag name |
group | string | — | Group name (alternative to name) |
fallback | string | Component | null | What to render when the flag is off |
inverted | boolean | false | Render when the flag is false |
tag | string | — | Wrap content in an HTML element (no wrapper by default) |
Slots
| Slot | Description |
|---|---|
default | Content when the flag is on |
fallback | Content when the flag is off |
loading | Content while flags are loading via loader |
v-feature directive
vue
<!-- Show when flag is on -->
<div v-feature="'newDashboard'">...</div>
<!-- Show when flag is off (inverted) -->
<div v-feature:not="'betaSearch'">...</div>
<!-- Show when ALL flags are on -->
<div v-feature="['newDashboard', 'betaSearch']">...</div>Works like v-show (toggles display: none) — the DOM node is always present. For v-if-like behavior use <Feature>.
useFeature
ts
import { useFeature } from 'vue-feature-toggles'
// Single flag → Ref<boolean>
const isNewDashboard = useFeature('newDashboard')
// Multiple flags → Record<string, Ref<boolean>>
const { newDashboard, betaSearch } = useFeature(['newDashboard', 'betaSearch'])
// AND check across multiple flags → Ref<boolean>
const allEnabled = useFeature('newDashboard', 'betaSearch')Multivariate flags & <FeatureVariant>
Flags can hold a string variant instead of a boolean — useful for A/B tests and multi-step rollouts.
ts
app.use(FeatureToggles, {
flags: { checkoutFlow: 'v2' },
})ts
import { useFeatureVariant } from 'vue-feature-toggles'
const variant = useFeatureVariant('checkoutFlow') // Ref<string>vue
<FeatureVariant name="checkoutFlow">
<template #v1><CheckoutV1 /></template>
<template #v2><CheckoutV2 /></template>
<template #fallback><CheckoutLegacy /></template>
</FeatureVariant>URL overrides work identically: ?feature:checkoutFlow=v2.