Client-Side Usage
Use feature flags in your Vue components with auto-imported composables.
Composables
useToggly
The main composable providing access to the full Toggly client.
<script setup>
const {
isReady, // Ref<boolean> - true when initial fetch completes
isLoading, // Ref<boolean> - true during any fetch
features, // Ref<Record<string, boolean>> - all feature states
error, // Ref<Error | null> - last error if any
refresh, // () => Promise<void> - manually refresh features
setIdentity, // (id: string) => Promise<void> - set user identity
destroy, // () => void - cleanup (called automatically)
} = useToggly()
// Wait for features to load
watch(isReady, (ready) => {
if (ready) {
console.log('Features loaded:', features.value)
}
})
// Set user identity after login
async function onLogin(userId: string) {
await setIdentity(userId)
}
</script>
useFeatureFlag
Check if a single feature is enabled.
<script setup>
// Basic usage
const { isEnabled, isLoading } = useFeatureFlag('new-dashboard')
// Reactive feature check
watch(isEnabled, (enabled) => {
if (enabled) {
analytics.track('new_dashboard_shown')
}
})
</script>
<template>
<div v-if="isLoading">Loading...</div>
<NewDashboard v-else-if="isEnabled" />
<OldDashboard v-else />
</template>
useFeatureOff
Check if a feature is disabled (inverted logic).
<script setup>
// Show content when maintenance mode is OFF
const { isEnabled: showContent } = useFeatureOff('maintenance-mode')
</script>
<template>
<MainContent v-if="showContent" />
<MaintenancePage v-else />
</template>
useFeatureGate
Check multiple features with logical operators.
<script setup>
// All features must be enabled
const { isEnabled: hasAll } = useFeatureGate(
['feature-a', 'feature-b', 'feature-c'],
'all'
)
// Any feature enabled
const { isEnabled: hasAny } = useFeatureGate(
['premium', 'trial', 'beta-access'],
'any'
)
// Negated - show when ALL features are OFF
const { isEnabled: showFallback } = useFeatureGate(
['new-ui'],
'all',
true // negate
)
</script>
<template>
<FullExperience v-if="hasAll" />
<PartialExperience v-else-if="hasAny" />
<BasicExperience v-else />
</template>
Entity context
Pass a page entity per composable or check — not via setIdentity. See Entity & page context.
The Nuxt client is a browser SDK: local registerContext only. It does not register schemas with the dashboard.
import { registerContext } from '@ops-ai/nuxt-toggly-core'
registerContext('Order', (order) => ({
kind: 'Order',
key: String(order.id),
attributes: { Status: order.status },
}))
<script setup>
const { isFeatureOn } = useToggly()
const order = useOrder()
const showBadge = await isFeatureOn('OrderBadge', order.value, 'Order')
</script>
Gates fail closed without entity context. setIdentity remains user only.
User Identity
Set user identity for percentage-based rollouts and user targeting.
Pass groups and claims at client init (see
Configuration). Runtime
setIdentity updates identity only — it does not change groups or claims.
Setting Identity
<script setup>
const { setIdentity } = useToggly()
// After user authentication
onMounted(async () => {
const user = await getCurrentUser()
if (user) {
await setIdentity(user.id)
}
})
// On login
async function handleLogin(credentials) {
const user = await login(credentials)
await setIdentity(user.id)
}
// On logout - clear identity
async function handleLogout() {
await setIdentity('')
}
</script>
Persistent Identity
Identity is persisted to localStorage by default (configurable):
export default defineNuxtConfig({
toggly: {
persistIdentity: true, // default
},
})
Refreshing Features
Features auto-refresh based on the refreshInterval config. You can also refresh manually:
<script setup>
const { refresh, isLoading } = useToggly()
async function forceRefresh() {
await refresh()
}
</script>
<template>
<button @click="forceRefresh" :disabled="isLoading">
Refresh Features
</button>
</template>
Error Handling
<script setup>
const { error, isReady } = useToggly()
watch(error, (err) => {
if (err) {
console.error('Toggly error:', err)
// Features keep last-known-good values when available, then fall back to defaults
}
})
</script>
<template>
<div v-if="error" class="error-banner">
Feature service unavailable. Using cached values.
</div>
</template>
For callback-based reporting with the direct client and the shared fallback contract, see Reliability and Error Handling.
SSR Considerations
The SDK handles SSR automatically:
- Server: Features fetched and cached server-side
- Hydration: Client receives server state, no flash
- Client: Takes over with reactive updates
<script setup>
const { isReady, isEnabled } = useFeatureFlag('my-feature')
// isReady is true immediately on client if SSR provided data
// No loading flash on hydration
</script>
Disable SSR for Specific Features
For client-only features, use ClientOnly:
<template>
<ClientOnly>
<Feature feature-key="client-only-feature">
<ClientOnlyComponent />
</Feature>
</ClientOnly>
</template>
Offline Support
Enable localStorage persistence for offline access:
export default defineNuxtConfig({
toggly: {
persistFeatures: true, // Cache features locally
},
})
When the API is unavailable, the SDK will:
- Use cached features from localStorage
- Fall back to
featureDefaultsif no cache - Retry on next refresh interval
TypeScript
All composables are fully typed:
import type { UseFeatureFlagReturn, UseTogglyReturn } from '@ops-ai/nuxt-toggly'
const flag: UseFeatureFlagReturn = useFeatureFlag('my-feature')
const toggly: UseTogglyReturn = useToggly()