src/skills/api-flags-posthog-flags/SKILL.md
PostHog feature flags, rollouts, A/B testing. Use when implementing gradual rollouts, A/B tests, kill switches, remote configuration, beta features, or user targeting with PostHog.
npx skillsauth add agents-inc/skills api-flags-posthog-flagsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Use PostHog feature flags for gradual rollouts, A/B testing, and remote configuration. Client-side:
useFeatureFlagEnabledhook. Server-side:posthog-nodewith local evaluation. Always pairuseFeatureFlagPayloadwithuseFeatureFlagEnabledfor experiments. Handle theundefinedloading state on every flag check.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST always pair useFeatureFlagPayload with useFeatureFlagEnabled or useFeatureFlagVariantKey for experiments - payload hooks don't send exposure events)
(You MUST use the feature flags secure API key (phs_*) for server-side local evaluation - personal API keys are deprecated for this use)
(You MUST handle the undefined state when flags are loading - never assume a flag is immediately available)
(You MUST include flag owner and expiry date in flag metadata - flags without owners become orphaned debt)
(You MUST wrap flag usage in a single function when used in multiple places - prevents orphaned flag code on cleanup)
</critical_requirements>
Auto-detection: PostHog feature flags, useFeatureFlagEnabled, useFeatureFlagPayload, useFeatureFlagVariantKey, PostHogFeature, isFeatureEnabled, getFeatureFlag, gradual rollout, A/B test, experiment, multivariate flag
When to use:
When NOT to use:
Key patterns covered:
Detailed Resources:
Feature flags decouple deployment from release. You can ship code to production but control who sees it and when. This enables:
Core principles:
When to use feature flags:
When NOT to use feature flags:
Use useFeatureFlagEnabled for simple on/off features. Always handle the undefined loading state -- treating it as false causes a flash of wrong UI.
const isNewCheckout = useFeatureFlagEnabled(FLAG_NEW_CHECKOUT);
if (isNewCheckout === undefined) return <Skeleton />; // Loading
if (isNewCheckout) return <NewCheckout />; // Enabled
return <LegacyCheckout />; // Disabled
Store flag keys as named constants in lib/feature-flags.ts to prevent typos and enable cleanup-by-grep.
See examples/core.md for full good/bad examples.
Use useFeatureFlagVariantKey for A/B tests with multiple variants. Define variant constants alongside the flag key. Switch on variants with a default fallback to control.
const variant = useFeatureFlagVariantKey(FLAG_PRICING_PAGE);
if (variant === undefined) return <Skeleton />;
switch (variant) {
case VARIANT_SIMPLE: return <SimplePricing />;
case VARIANT_DETAILED: return <DetailedPricing />;
default: return <ControlPricing />;
}
See examples/core.md for full example.
The PostHogFeature component provides automatic exposure tracking and built-in fallback handling with less boilerplate. Use match={true} for boolean flags or match={VARIANT_KEY} for specific variants.
<PostHogFeature flag={FLAG_BETA} match={true} fallback={<Legacy />}>
<NewFeature />
</PostHogFeature>
See examples/core.md for boolean and variant examples.
Use useFeatureFlagPayload for dynamic JSON configuration. Always pair with useFeatureFlagEnabled -- the payload hook alone does NOT send exposure events, breaking experiment tracking.
const isEnabled = useFeatureFlagEnabled(FLAG_BANNER); // Sends exposure event
const payload = useFeatureFlagPayload(FLAG_BANNER); // Gets config
const config = payload ?? DEFAULT_BANNER_CONFIG;
See examples/core.md for full good/bad examples.
Use posthog-node with the Feature Flags Secure API Key (phs_*) for local evaluation. This reduces latency from ~500ms (network call) to ~10-50ms (local). The personalApiKey config option takes the phs_* key despite its legacy name.
export const posthog = new PostHog(process.env.POSTHOG_API_KEY!, {
host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
personalApiKey: process.env.POSTHOG_FEATURE_FLAGS_KEY, // phs_* key
featureFlagsPollingInterval: POSTHOG_POLL_INTERVAL_MS, // default 30s
});
See examples/server-side.md for API handler usage, local-only evaluation, and distributed/serverless environments.
Every flag needs an owner, a creation date, and an expected removal date. Wrap flag checks in a single helper function so cleanup is a one-file change.
/**
* Owner: @john-doe | Created: 2025-01-15 | Remove by: 2025-02-15
*/
export const FLAG_NEW_CHECKOUT = "new-checkout-flow";
export function isNewCheckoutEnabled(flag: boolean | undefined): boolean {
return flag === true; // When removing: change to `return true;`
}
See examples/core.md for full documentation patterns and stale flag detection.
</patterns><red_flags>
High Priority Issues:
useFeatureFlagPayload alone for experiments (no exposure tracking)phs_*) on client (security violation)Medium Priority Issues:
Common Mistakes:
Gotchas & Edge Cases:
phs_*) - personal API keys are deprecatedonFeatureFlags callback receives three parameters: flags, flagVariants, { errorsLoading } (third parameter)</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST always pair useFeatureFlagPayload with useFeatureFlagEnabled or useFeatureFlagVariantKey for experiments - payload hooks don't send exposure events)
(You MUST use the feature flags secure API key (phs_*) for server-side local evaluation - personal API keys are deprecated for this use)
(You MUST handle the undefined state when flags are loading - never assume a flag is immediately available)
(You MUST include flag owner and expiry date in flag metadata - flags without owners become orphaned debt)
(You MUST wrap flag usage in a single function when used in multiple places - prevents orphaned flag code on cleanup)
Failure to follow these rules will cause incorrect experiment results, security vulnerabilities, UI flashing, and technical debt.
</critical_reminders>
development
Material Design component library for Vue 3
development
VitePress 1.x — Vue-powered static site generator for documentation sites, built on Vite
tools
Docusaurus 3.x documentation framework — site configuration, docs/blog plugins, sidebars, versioning, MDX, swizzling, and deployment
development
TanStack Form patterns - useForm, form.Field, validators, arrays, linked fields, createFormHook, type safety