Skip to content

Usage Guide

Client-Side Usage

Basic Flag Checking

Use the useFeatureFlags composable in your Vue components:

vue
<script setup>
const { isEnabled, getVariant, getValue } = useFeatureFlags()

// Check if a flag is enabled
const showNewFeature = isEnabled('newFeature')

// Get variant assignment
const variant = getVariant('experiment')

// Get flag value
const maxItems = getValue('maxItems')
</script>

<template>
  <div>
    <!-- Simple conditional rendering -->
    <NewFeature v-if="showNewFeature" />
    
    <!-- Variant-based rendering -->
    <div v-if="variant === 'treatment'">
      Treatment version
    </div>
  </div>
</template>

Using the v-feature Directive

The v-feature directive provides a declarative way to conditionally render elements:

vue
<template>
  <!-- Show element if flag is enabled -->
  <div v-feature="'newDashboard'">
    <h1>Welcome to the New Dashboard!</h1>
  </div>
  
  <!-- Show for specific variant -->
  <button v-feature="'buttonDesign:control'">
    Original Button
  </button>
  
  <button v-feature="'buttonDesign:treatment'">
    New Button Design
  </button>
</template>

Note: The v-feature directive is client-side only. For server-rendered content, use v-if with isEnabled().

Accessing All Flags

vue
<script setup>
const { flags } = useFeatureFlags()

// Access all resolved flags
console.log(flags.value)
// {
//   newDashboard: { enabled: true, value: true },
//   experiment: { enabled: true, value: 'treatment', variant: 'treatment' }
// }

// Watch for flag changes
watch(flags, (newFlags) => {
  console.log('Flags updated:', newFlags)
})
</script>

Manually Refreshing Flags

vue
<script setup>
const { fetch, flags } = useFeatureFlags()

// Refresh flags after user login
async function handleLogin(user) {
  await loginUser(user)
  
  // Refresh flags to get user-specific flags
  await fetch()
  
  console.log('Updated flags:', flags.value)
}
</script>

Server-Side Usage

API Routes

Use getFeatureFlags in your server routes:

ts
// server/api/dashboard.ts
export default defineEventHandler(async (event) => {
  const { isEnabled, getVariant, getValue } = getFeatureFlags(event)

  // Feature gating
  if (!isEnabled('newDashboard')) {
    throw createError({
      statusCode: 404,
      message: 'Dashboard not available'
    })
  }

  // Get variant for A/B test
  const layoutVariant = getVariant('dashboardLayout')
  
  // Get configuration value
  const maxWidgets = getValue('maxDashboardWidgets') || 6

  return {
    layout: layoutVariant,
    maxWidgets,
    data: await fetchDashboardData()
  }
})

Middleware

Use flags in server middleware for request-level logic:

ts
// server/middleware/feature-gate.ts
export default defineEventHandler((event) => {
  const { isEnabled } = getFeatureFlags(event)
  
  // Block access to beta routes
  if (event.path.startsWith('/api/beta') && !isEnabled('betaAccess')) {
    throw createError({
      statusCode: 403,
      message: 'Beta access required'
    })
  }
})

Accessing All Flags

ts
export default defineEventHandler((event) => {
  const { flags } = getFeatureFlags(event)
  
  // Return all flags to client
  return {
    features: Object.entries(flags).reduce((acc, [key, flag]) => {
      acc[key] = {
        enabled: flag.enabled,
        variant: flag.variant
      }
      return acc
    }, {} as Record<string, any>)
  }
})

Working with Variants

A/B Testing

vue
<script setup>
const { getVariant, getValue } = useFeatureFlags()

// Get which variant the user is assigned to
const buttonVariant = getVariant('buttonDesign')

// Get the value for the user's variant
const buttonConfig = getValue('buttonDesign')

// Track which variant is shown
onMounted(() => {
  analytics.track('button_variant_shown', { variant: buttonVariant })
})

function handleClick() {
  analytics.track('button_clicked', { variant: buttonVariant })
}
</script>

<template>
  <button 
    :class="`btn-${buttonConfig.color}`"
    @click="handleClick"
  >
    {{ buttonConfig.text }}
  </button>
</template>

Gradual Rollouts

ts
// feature-flags.config.ts
export default defineFeatureFlags(() => ({
  newCheckout: {
    enabled: true,
    variants: [
      { name: 'old', weight: 80, value: false },
      { name: 'new', weight: 20, value: true }  // 20% get new checkout
    ]
  }
}))
vue
<script setup>
const { getValue } = useFeatureFlags()
const useNewCheckout = getValue('newCheckout')
</script>

<template>
  <NewCheckoutFlow v-if="useNewCheckout" />
  <OldCheckoutFlow v-else />
</template>

Type Safety

The module automatically generates TypeScript types:

ts
const { isEnabled, getValue } = useFeatureFlags()

// ✅ Type-safe - flag exists
isEnabled('newDashboard')

// ❌ TypeScript error - flag not declared
isEnabled('unknownFlag')

// ✅ Type-safe value access
const maxItems: number = getValue('maxItems')

Best Practices

1. Conditional Rendering

vue
<template>
  <div>
    <!-- Simple flag check -->
    <NewFeature v-if="isEnabled('newFeature')" />
    
    <!-- Combined with other conditions -->
    <BetaFeature 
      v-if="isEnabled('betaFeature') && user.canAccess" 
      :user="user"
    />
    
    <!-- Toggle between versions -->
    <NewDashboard v-if="isEnabled('newDashboard')" />
    <LegacyDashboard v-else />
  </div>
</template>

2. Server-Side Protection

Always protect sensitive features on both client and server:

ts
// server/api/premium-feature.ts
export default defineEventHandler(async (event) => {
  const { isEnabled } = getFeatureFlags(event)

  if (!isEnabled('premiumFeature')) {
    throw createError({
      statusCode: 403,
      message: 'Premium feature not available'
    })
  }

  return {
    // Premium feature data
  }
})

3. Use Computed Properties

vue
<script setup>
const { isEnabled, getValue } = useFeatureFlags()

// Cache flag checks in computed properties
const features = computed(() => ({
  newDashboard: isEnabled('newDashboard'),
  darkMode: isEnabled('darkMode'),
  maxItems: getValue('maxItems') || 20
}))
</script>

<template>
  <div v-if="features.newDashboard">
    <Dashboard 
      :dark="features.darkMode" 
      :max-items="features.maxItems" 
    />
  </div>
</template>

4. Track Variant Exposure

vue
<script setup>
const { getVariant } = useFeatureFlags()

const variant = getVariant('experiment')

// Track when user sees a variant
onMounted(() => {
  if (variant) {
    analytics.track('experiment_viewed', { variant })
  }
})
</script>

Next Steps

Released under the MIT License.