From frontendskills
Use when adding feature flags to a frontend — wires the vendor-agnostic OpenFeature SDK (a useFlag hook in React, a composable in Vue) with safe defaults, an evaluation context for user targeting, a dev override, and a pattern for gating routes behind flags. Swap providers (PostHog/GrowthBook/LaunchDarkly/…) in one line.
How this skill is triggered — by the user, by Claude, or both
Slash command
/frontendskills:set-up-feature-flagsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```bash
grep -E '"(@openfeature/web-sdk|@openfeature/react-sdk)"' package.json 2>/dev/null
grep -rn "import.meta.env.VITE_FEATURE_\|featureFlag\|useFlag" src/ 2>/dev/null | head
Look for ad-hoc env-var flags (VITE_FEATURE_X) — those are build-time toggles, not runtime flags; this skill replaces them where you need runtime control. Pairs with set-up-auth (targeting context = the logged-in user) and set-up-routing (flag-gated routes).
React → @openfeature/react-sdk (provider + useFlag). Vue → @openfeature/web-sdk + a small composable.
pnpm add @openfeature/web-sdk @openfeature/react-sdk # Vue: just @openfeature/web-sdk
// src/libs/featureFlags.ts
import { OpenFeature, InMemoryProvider } from '@openfeature/web-sdk';
// Dev/test: in-memory flags. Prod: your vendor's OpenFeature provider
// (PostHog / GrowthBook / LaunchDarkly / ConfigCat / Flagsmith) — a one-line swap.
const provider = new InMemoryProvider({
'new-dashboard': { variants: { on: true, off: false }, defaultVariant: 'off', disabled: false },
});
export function initFeatureFlags() {
void OpenFeature.setProviderAndWait(provider);
}
OpenFeatureProvider + useFlag// main.tsx
import { OpenFeatureProvider } from '@openfeature/react-sdk';
import { initFeatureFlags } from '@/libs/featureFlags';
initFeatureFlags();
<OpenFeatureProvider>
<App />
</OpenFeatureProvider>
// usage — query-style hook with a mandatory safe default
import { useFlag } from '@openfeature/react-sdk';
function Dashboard() {
const { value: showNew } = useFlag('new-dashboard', false); // default = control
return showNew ? <NewDashboard /> : <ClassicDashboard />;
}
The React SDK re-renders on flag/context change and supports Suspense while the provider initializes.
// src/composables/useFlag.ts
import { OpenFeature } from '@openfeature/web-sdk';
import { ref, onUnmounted } from 'vue';
export function useFlag(key: string, defaultValue: boolean) {
const client = OpenFeature.getClient();
const value = ref(client.getBooleanValue(key, defaultValue));
const handler = () => { value.value = client.getBooleanValue(key, defaultValue); };
client.addHandler('PROVIDER_CONFIGURATION_CHANGED', handler);
onUnmounted(() => client.removeHandler('PROVIDER_CONFIGURATION_CHANGED', handler));
return value;
}
Set the evaluation context from the current user — the provider targets on it (plan, % rollout, allow-list). Update it on login (set-up-auth):
import { OpenFeature } from '@openfeature/web-sdk';
await OpenFeature.setContext({ targetingKey: user.id, plan: user.plan, country: user.country });
Never hand-code if (user.id === 'me') — that's what targeting is for.
// React (TanStack Router): src/routes/new-dashboard.tsx
import { OpenFeature } from '@openfeature/web-sdk';
export const Route = createFileRoute('/new-dashboard')({
beforeLoad: () => {
if (!OpenFeature.getClient().getBooleanValue('new-dashboard', false)) throw notFound();
},
});
Dev override: seed the InMemoryProvider from a local panel / localStorage so you can flip flags without the backend; OpenFeature also supports a multi-provider for layering overrides on top of the real provider.
pnpm tsc --noEmit
pnpm dev
Flip defaultVariant (or the dev override) → the gated UI/route appears; the safe default (control) renders when the provider is unreachable.
npx claudepluginhub velimirmueller/claude_development_skills --plugin frontendskillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.