Feature flag management with boolean and token-based features, perfect for A/B testing, progressive rollout, and feature toggles.
Features
- Boolean features (true/false activation)
- Token features with $variation support
- Auto-selection of enabled features
- Multi-select support for feature combinations
- Adapter pattern for external feature flag services
- Reactive feature state updates
Installation
import { createFeaturesPlugin } from '@vuetify/v0'
const app = createApp(App)
app.use(createFeaturesPlugin({
features: {
'dark-mode': true,
'theme-color': { $variation: 'blue' },
},
}))
Basic Usage
<script setup lang="ts">
import { useFeatures } from '@vuetify/v0'
const features = useFeatures()
const isDarkMode = computed(() =>
features.selectedIds.has('dark-mode')
)
const themeColor = features.variation('theme-color', 'blue')
</script>
<template>
<div :class="{ dark: isDarkMode }">
<p>Theme color: {{ themeColor }}</p>
</div>
</template>
API Reference
createFeaturesPlugin()
Creates a features plugin.
Plugin configurationfeatures
Record<ID, boolean | TokenCollection>
Static feature flags to registerExample:{
'dark-mode': true,
'beta-feature': false,
'theme-variant': { $variation: 'blue' },
}
adapter
FeaturesAdapterInterface | FeaturesAdapterInterface[]
Feature flag adapter(s) for external services
namespace
string
default:"'v0:features'"
The namespace for the features context
FeatureContext
Number of registered features
Map of all registered features
Set of currently selected (enabled) feature IDs
register
(registration: Partial<FeatureTicketInput>) => FeatureTicket
Register a new featureExample:features.register({
id: 'new-feature',
value: true,
})
variation
(id: ID, fallback?: unknown) => unknown
Get the variation value of a featureFor token features with $variation, returns the variation value.
For boolean features, returns the boolean value.
Returns fallback if feature doesn’t exist or has no variation.
sync
(flags: FeaturesAdapterFlags) => void
Sync feature flags from an external sourceUpdates existing flags and registers new ones. Use this when adapter flags change.
get
(id: ID) => FeatureTicket | undefined
Get a feature by ID
Check if a feature exists
Feature Types
Boolean Features
Simple on/off feature flags:
app.use(createFeaturesPlugin({
features: {
'dark-mode': true,
'beta-feature': false,
},
}))
// In component
const features = useFeatures()
const isDarkMode = features.selectedIds.has('dark-mode') // true
const hasBeta = features.selectedIds.has('beta-feature') // false
Token Features
Features with variation data:
app.use(createFeaturesPlugin({
features: {
'theme-color': { $variation: 'blue' },
'layout-mode': { $variation: 'compact' },
},
}))
// In component
const features = useFeatures()
const themeColor = features.variation('theme-color') // 'blue'
const layoutMode = features.variation('layout-mode') // 'compact'
Features with Explicit State
app.use(createFeaturesPlugin({
features: {
'premium-feature': {
$value: true,
$variation: { tier: 'gold', limit: 100 },
},
},
}))
// In component
const features = useFeatures()
const isEnabled = features.selectedIds.has('premium-feature') // true
const config = features.variation('premium-feature')
// { tier: 'gold', limit: 100 }
Dynamic Features
Register Features at Runtime
const features = useFeatures()
// Register new feature
features.register({
id: 'new-feature',
value: true,
})
// Check if enabled
if (features.selectedIds.has('new-feature')) {
// Feature is enabled
}
Toggle Features
const features = useFeatures()
// Enable feature
features.select('dark-mode')
// Disable feature
features.unselect('dark-mode')
// Enable multiple features
features.select(['feature-a', 'feature-b'])
External Adapters
LaunchDarkly Adapter
import { createFeaturesPlugin } from '@vuetify/v0'
import { LaunchDarklyAdapter } from '@vuetify/v0/features/adapters'
app.use(createFeaturesPlugin({
adapter: new LaunchDarklyAdapter({
clientId: 'your-client-id',
user: { key: 'user-123' },
}),
}))
PostHog Adapter
import { PostHogAdapter } from '@vuetify/v0/features/adapters'
app.use(createFeaturesPlugin({
adapter: new PostHogAdapter({
apiKey: 'your-api-key',
host: 'https://app.posthog.com',
}),
}))
Custom Adapter
import type { FeaturesAdapterInterface } from '@vuetify/v0'
class MyFeatureAdapter implements FeaturesAdapterInterface {
setup(onUpdate: (flags: FeaturesAdapterFlags) => void) {
// Return initial flags
const flags = {
'my-feature': true,
'theme': { $variation: 'dark' },
}
// Set up listener for flag updates
myService.onFlagsChanged((newFlags) => {
onUpdate(newFlags)
})
return flags
}
dispose() {
// Cleanup
}
}
app.use(createFeaturesPlugin({
adapter: new MyFeatureAdapter(),
}))
Multiple Adapters
app.use(createFeaturesPlugin({
adapter: [
new LaunchDarklyAdapter({ /* ... */ }),
new PostHogAdapter({ /* ... */ }),
],
}))
Reactive Updates
<script setup lang="ts">
import { useFeatures } from '@vuetify/v0'
import { watchEffect } from 'vue'
const features = useFeatures()
watchEffect(() => {
if (features.selectedIds.has('beta-ui')) {
console.log('Beta UI enabled')
}
})
</script>