
Setting Feature Flags in Storybook
FreeManage feature flags effectively in Storybook stories.
Free · Opens the source repo
What Setting Feature Flags in Storybook does
This skill provides guidance for developers working with Storybook when implementing feature flags for components. It emphasizes the correct use of the featureFlags story parameter, which is crucial for visual regression testing. By using this parameter, developers can ensure that the visual representation of components accurately reflects the state of feature flags, preventing misleading snapshots during testing.
The skill explains the difference between boolean flags and multivariate flags, detailing how to set them up correctly in Storybook. Boolean flags can be simply added to the featureFlags array, while multivariate flags require a record form to specify the variant. This distinction is important for ensuring that the correct flags are applied at both the meta and story levels, as the parameters defined at the story level will replace any meta-level flags.
A significant issue addressed by this skill is the common pitfall of imperatively setting feature flags using featureFlagLogic.actions.setFeatureFlags(...). This approach can lead to incorrect visual regression snapshots since it may not work as expected during the visual regression runtime. Instead, the skill advocates for the use of the featureFlags parameter, which ensures that flags are properly merged and retained during rendering.
Overall, this skill is designed for developers who need to manage feature flags within Storybook effectively, ensuring that their visual regression tests accurately reflect the intended component states based on feature flags.
When to use it
Use this skill when writing Storybook stories for components that depend on feature flags, especially when testing visual regressions.
When not to use it
This skill may not be necessary if you are not using feature flags in your Storybook stories or if you do not require visual regression testing.
What you can build with it
Testing a New Feature
When developing a new feature, use this skill to ensure that the feature flag is set correctly in your Storybook story.
Visual Regression Testing
Utilize the skill to manage feature flags effectively, ensuring that visual regression tests accurately reflect the component's state.
Experimenting with Variants
When testing different variants of a component, use the multivariate flag setup to control which version is rendered.
How to install Setting Feature Flags in Storybook
View source1. Install with the skills CLI
npx skills add posthog/posthog/setting-feature-flags-in-storybook --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by posthogSetting feature flags in Storybook
[!WARNING] Never call
featureFlagLogic.actions.setFeatureFlags(...)from a story. It silently no-ops in the visual-regression runtime (rendering the flag-OFF branch) while passing in jest — so unit tests stay green and the snapshot is wrong. Use thefeatureFlagsstory parameter instead.
Mental model: boolean flags always work (they ride the always-merged baseline);
variant values need a gate that only the featureFlags parameter opens correctly.
How to use it
This is the stable contract — prefer it over anything in "Under the hood" below.
Boolean flags (flag is simply on)
const meta: Meta = {
title: 'Scenes/MyScene',
parameters: {
featureFlags: [FEATURE_FLAGS.MY_FLAG, FEATURE_FLAGS.OTHER_FLAG],
},
}
Array entries are flags that evaluate to true. This is the common case.
Multivariate flags (pin a specific variant)
For a flag whose value is a variant string (experiment arms, multivariate rollouts), use
the record form — the array form can only express true:
// meta-level: applies to every story in the file
parameters: { featureFlags: { [FEATURE_FLAGS.THEME_OVERRIDE]: 'intent_plus' } }
// per-story: a different arm per story
export const ControlArm: Story = {
parameters: { featureFlags: { [FEATURE_FLAGS.THEME_OVERRIDE]: 'control' } },
}
export const TreatmentArm: Story = {
parameters: { featureFlags: { [FEATURE_FLAGS.THEME_OVERRIDE]: 'intent_plus' } },
}
You can mix booleans and variants in one record: { 'some-bool-flag': true, 'my-experiment': 'test_b' }.
[!IMPORTANT] A story's
parametersreplace the meta's (shallow merge), so a per-storyfeatureFlagsdrops every flag set at the meta level. Re-list any meta flags you still need — silently losing one renders the flag-off branch and is easy to miss.
Why the obvious approach fails
Setting flags imperatively (featureFlagLogic.actions.setFeatureFlags) works in jest
(NODE_ENV==='test') but not in the built visual-regression Storybook. posthog-js loads
flags and fires onFeatureFlags with an empty set, which dispatches setFeatureFlags
and wipes whatever you set imperatively — so the unit test passes while the snapshot
renders the flag-OFF branch. The featureFlags parameter avoids this by writing flags to
the always-merged baseline instead (below), so the empty callback can't clobber them.
Do not try to fix this by disabling posthog-js flags (e.g.
advanced_disable_feature_flags). The app shell (appLogic.showApp) only renders oncereceivedFeatureFlagsis true, which is set by that sameonFeatureFlagscallback — suppress it and everyScenes-App/*story stalls behind a 3s timeout and flakes.
Under the hood (implementation detail — may drift)
This explains why the parameter works, for trust and for anyone extending the harness. Treat "How to use it" above as the contract, not this.
withFeatureFlags → setFeatureFlags (frontend/src/mocks/browser.tsx) writes the
flags (array or record) straight to window.POSTHOG_APP_CONTEXT.persisted_feature_flags.
getPersistedFeatureFlags (frontend/src/lib/logic/featureFlagLogic.ts) reads that as
featureFlagLogic's initial value and spyOnFeatureFlags always merges it as the
baseline — so both booleans and pinned variants survive the empty onFeatureFlags
callback. The only production-side support this needs is getPersistedFeatureFlags
accepting the record form (variant values) in addition to the server's array form.
You should not need to touch any of this. If you're extending the harness, that's the seam.
See also
The featureFlags parameter only controls the flag. If a component's render also depends
on other runtime state (localStorage, an APP_CONTEXT field, a kea logic that resolves an
entry), stage that state too — typically in a small wrapper the story renders that sets it
and mounts the logic before rendering the component. Keep that wrapper in the story file;
don't add test-only props to the production component to make it renderable.
Frequently asked questions about Setting Feature Flags in Storybook
Similar skills
Playwright Component Testing
Test React and Vue components in isolation with Playwright.
Fluent UI Blazor
Integrate Fluent UI components in Blazor applications effortlessly.
Build MCP App
Create interactive UI widgets for MCP servers.
Web Design Reviewer
Identify and fix design issues in websites efficiently.
Markstream Install
Seamlessly integrate Markstream for Markdown rendering.
GSAP & Framer Scroll Animation
Create advanced scroll animations effortlessly.
