Skip to main content
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.
options
FeaturePluginOptions
Plugin configuration
features
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

size
number
Number of registered features
collection
Map<ID, FeatureTicket>
Map of all registered features
selectedIds
Set<ID>
Set of currently selected (enabled) feature IDs
register
(registration: Partial<FeatureTicketInput>) => FeatureTicket
Register a new featureExample:
features.register({
  id: 'new-feature',
  value: true,
})
select
(id: ID | ID[]) => void
Enable feature(s)
unselect
(id: ID | ID[]) => void
Disable feature(s)
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
has
(id: ID) => boolean
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>

Build docs developers (and LLMs) love