This FRD ships @dmwd-io/feature-flags as an optional package that re-exports @growthbook/growthbook as the platform standard for feature flags and A/B experiments via GrowthBook. The value is standards and drift prevention — a single designated entry point with documented env var conventions — not a custom abstraction layer.
Introduction
Overview
Every app built on the design system needs rollout controls — gradual rollouts, A/B experiments, kill switches, and environment-specific toggles. Currently each app either hard-codes if (process.env.FEATURE_X) checks, imports a vendor SDK (LaunchDarkly, Flagsmith, Unleash) directly, or skips flags entirely and deploys everything at once. Per ADR-014 (Open Source First), this FRD designates @growthbook/growthbook as the community library for feature flags and re-exports it through @dmwd-io/feature-flags. Apps import from the platform package, and the platform documents GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST as the standard env var conventions. No custom provider interface is built — GrowthBook’s own API is the interface.
Goals
Designate @growthbook/growthbook as the platform standard for feature flags and A/B experiments (per ADR-014).
Ship @dmwd-io/feature-flags as a thin re-export of @growthbook/growthbook to standardize the import path and prevent drift.
Document GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST as the canonical platform env var names.
Ensure SSR-safe operation — GrowthBook supports server-side flag loading natively.
Document the need to add GrowthBook to ADR-027 as the designated feature flag solution.
Non-Goals
Building a custom provider interface or adapter layer — the library’s own API is the interface (per ADR-014).
LaunchDarkly, Flagsmith, or Unleash adapters (SaaS options; prefer GrowthBook self-hosted per platform philosophy).
Implementing a flag management UI or admin dashboard.
Building a targeting rules engine (percentage rollouts, user segment matching) — that is the vendor’s responsibility.
Real-time flag streaming/polling — GrowthBook handles transport natively.
Analytics integration for experiment tracking (see FRD: Analytics Provider Wrapper).
Scope
In Scope
Area
Description
@dmwd-io/feature-flags package
Thin re-export of @growthbook/growthbook; single canonical import path for all platform apps
Env var conventions
GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST documented as platform-standard names
SSR bootstrap
Documented pattern for server-side flag loading using GrowthBook’s native API
Storybook docs
Example usage, SSR bootstrap flow, and multi-variant experiment patterns
ADR-027 supplement
Recommendation to formalize GrowthBook as the designated feature flag solution
Out of Scope
Area
Reason
Custom provider interface
ADR-014: library API is the interface
Test adapter implementation
GrowthBook provides its own testing utilities
Factory function wrapper
Adds indirection without value; apps use GrowthBook’s init directly
Custom React hooks/components
GrowthBook’s @growthbook/growthbook-react package covers this
Flag management UI
Vendor-hosted or separate admin tooling
Targeting rules engine
Vendor responsibility
Experiment analytics
Covered by FRD: Analytics Provider Wrapper
Users and Pain Points
User Groups
User
Description
Needs
App developers
Engineers shipping features incrementally
Typed flag checks that work in SSR and client-side rendering
QA engineers
Testers validating feature behavior under different flags
Deterministic test adapter to set any flag combination
Product managers
Stakeholders controlling rollout
A standard contract that connects to any vendor’s dashboard
Pain Points
User
Pain Point
Impact
App developers
Feature flags are process.env checks with no type safety — removed flags cause silent bugs
Stale flag checks persist in code; runtime errors in production
App developers
No SSR support — flag evaluation on the client causes layout flicker
Poor user experience during hydration
QA engineers
Cannot set flag values in Storybook — stories always show the default state
Flag-gated features are not demoed or tested in isolation
App developers
Vendor SDK imports scatter across components
Vendor lock-in; migration requires touching every component
Definitions
Term
Definition
Feature flag
A named toggle that controls whether a feature is active for a given context
Flag value
The resolved value of a flag — boolean for on/off, string for multi-variant experiments
Evaluation context
User and environment attributes used for targeting (user ID, tenant, environment, etc.)
Bootstrap
Pre-loading flag values on the server so the client renders with correct values immediately
Experiment
A multi-variant flag where users are assigned to different variants (e.g. “control”, “variant-a”, “variant-b”)
Kill switch
A flag used to disable a feature instantly without a deployment
Thin re-export
A package that imports and re-exports a community library, adding only platform conventions
Current State
Existing Behavior
No feature flag abstraction exists in the design system. Apps use one of three approaches: (1) process.env.NEXT_PUBLIC_FEATURE_X === "true" checks, (2) direct LaunchDarkly/Flagsmith SDK imports in components, or (3) no flags at all — features ship as all-or-nothing deployments.
Current Limitations
No shared TypeScript types for flags or evaluation context.
No SSR-safe flag evaluation — client-only checks cause hydration mismatches.
No test adapter — flag-dependent code paths are tested by setting environment variables or mocking vendor SDKs.
No React helpers — each app writes its own useFlag hook wrapping a vendor SDK.
Flag names are untyped strings — typos and removed flags are not caught at compile time.
Existing Workarounds
Apps wrap vendor SDK calls in custom hooks with ad-hoc caching.
Storybook stories hard-code feature states with args instead of using a flag provider.
Environment variable checks are scattered throughout components.
Proposed Solution
Summary
Per ADR-014 (Open Source First), @dmwd-io/feature-flags re-exports @growthbook/growthbook as the platform standard. No custom interface is built — the library’s API is the interface. Apps import from the platform package:
The package documents two platform-standard env var names:
GROWTHBOOK_CLIENT_KEY — the SDK client key for the GrowthBook API
GROWTHBOOK_API_HOST — the self-hosted GrowthBook instance URL (defaults to https://cdn.growthbook.io)
GrowthBook natively supports SSR bootstrap, multi-variant experiments, typed flag definitions via its SDK, and React helpers via @growthbook/growthbook-react. The platform package can optionally re-export from @growthbook/growthbook-react as well to provide a single import path.
User Experience
End users see fewer flickers during page load (flags resolved server-side via GrowthBook’s native bootstrap) and more consistent feature behavior (flags evaluated uniformly across the platform).
Developer Experience
Developers initialize GrowthBook once using platform-standard env vars and get the full GrowthBook feature set — typed attributes, multi-variant experiments, SSR support — without any custom abstraction to learn:
Flag names autocomplete via GrowthBook’s typed feature definitions. Storybook stories use GrowthBook’s built-in test utilities to set flag values deterministically.
7a. ADR-027 Gap
Feature flags are not yet designated in ADR-027. This FRD recommends opening an ADR-027 supplement to add GrowthBook as the default feature flag solution. GrowthBook is open-source, self-hosted, supports A/B testing, and aligns with the platform’s preference for self-hosted tools (PostHog, GlitchTip, Meilisearch).
GrowthBook’s useFeature returns an object with .on, .off, .value, and .experiment — richer than a simple boolean.
SSR bootstrap uses gb.setFeatures(serializedFlags) to hydrate without a client-side API call.
GrowthBook supports typed feature definitions via its SDK — see the GrowthBook docs for the TypeScript code generation workflow.
Accessibility Requirements
ID
Requirement
Notes
A11Y-001
IfFeatureEnabled must not produce empty DOM nodes that confuse screen readers
When flag is off, render null, not an empty wrapper
A11Y-002
Flag-gated content must not cause focus loss when flags change
If visible content is removed by a flag change, focus should move to a sensible target
Checklist
Keyboard support is defined. (IfFeatureEnabled is transparent to keyboard navigation)
Focus behavior is defined. (Flag changes should not orphan focus)
Screen reader behavior is defined. (IfFeatureEnabled renders null when off, no phantom elements)
Color contrast requirements are met. (N/A — no visual output)
Reduced motion behavior is considered. (N/A — no animation)
Semantic HTML expectations are documented. (IfFeatureEnabled renders no wrapper element)
ARIA usage is defined only where needed. (N/A)
Content and Documentation Requirements
ID
Requirement
Location
Priority
DOC-001
Storybook docs page explaining the feature flags pattern and @dmwd-io/feature-flags package
Storybook
Must
DOC-002
Inline JSDoc on any platform-specific utilities or conventions added to the package
Source code
Must
DOC-003
Example: SSR bootstrap flow using GrowthBook’s native setFeatures
Storybook
Must
DOC-004
Example: Storybook story showing a component in both flag-on and flag-off states
Storybook
Must
DOC-005
Example: multi-variant experiment using useFeature with variant values
Storybook
Should
Dependencies
Dependency
Type
Owner
Status
Notes
@growthbook/growthbook
Runtime (peer)
GrowthBook OSS
Ready
Community library designated per ADR-014
@growthbook/growthbook-react
Runtime (peer, optional)
GrowthBook OSS
Ready
React hooks and components
ADR-014 (Open Source First)
Architecture
Engineering
Ready
Governs the thin re-export approach
ADR-051 provider pattern
Architecture
Engineering
Ready
General provider conventions
React (peer dependency)
Runtime
React team
Ready
Required for React helper re-exports
Risks and Tradeoffs
Risk / Tradeoff
Impact
Mitigation
Adopting GrowthBook’s API directly means platform apps are coupled to GrowthBook’s interface
Migration to another tool requires updating all call sites
GrowthBook is open-source and self-hosted; per ADR-014 this is the acceptable tradeoff for avoiding custom abstraction maintenance
GrowthBook SDK updates may introduce breaking changes
Apps need to update when major versions ship
Pin @growthbook/growthbook to a tested version in @dmwd-io/feature-flags; update deliberately
No custom interface means no compile-time enforcement of platform-specific conventions (PII sanitization, event naming)
Teams may bypass conventions
Document conventions clearly; enforce via code review and linting rules
Real-time flag streaming requires GrowthBook server-sent events support
Flag changes require configuration of GrowthBook’s streaming endpoint
Document streaming setup; it is native to GrowthBook and does not require custom code
Open Questions
ID
Question
Owner
Status
Resolution
Q-001
Should @dmwd-io/feature-flags also re-export @growthbook/growthbook-react, or keep it as a separate import?
David Holmes
Open
—
Q-002
Should the platform provide a pre-configured createGrowthBook() helper that reads GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST automatically?
David Holmes
Open
—
Q-003
Should flag evaluation context include request headers for server-side targeting (e.g. geo, device)?
David Holmes
Open
—
Q-004
Should @dmwd-io/feature-flags export a platform-standard GrowthBookProvider wrapper for React apps?
David Holmes
Open
—
Acceptance Criteria
ID
Criteria
Related Requirement
AC-001
import { GrowthBook } from '@dmwd-io/feature-flags' resolves correctly in a TypeScript project
FR-001
AC-002
GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST are documented in the package README and Storybook page
FR-002
AC-003
SSR bootstrap example compiles and runs without errors
FR-003
AC-004
pnpm typecheck passes on the package
NFR-002
AC-005
No custom provider interface or adapter is present in the package source
NFR-002
AC-006
@growthbook/growthbook appears as a peer dependency, not a bundled dependency, in package.json
NFR-003
LLM Handoff Instructions
Expected LLM Behavior
Create packages/feature-flags/ directory (or follow the existing packages directory structure in the repo).
Create packages/feature-flags/package.json with @growthbook/growthbook and @growthbook/growthbook-react as peer dependencies.
Create packages/feature-flags/src/index.ts that re-exports everything from @growthbook/growthbook and (optionally) @growthbook/growthbook-react.
Document GROWTHBOOK_CLIENT_KEY and GROWTHBOOK_API_HOST as the platform-standard env var names in the package README or a docs/ file.
Run pnpm typecheck to confirm the package compiles cleanly.
LLM Should Not
Build a custom FeatureFlagsProvider interface, adapter, or factory function.
Import and re-wrap GrowthBook’s API in custom hooks or components.
Add runtime dependencies beyond @growthbook/growthbook and @growthbook/growthbook-react (peers).
Implement targeting rules, percentage rollouts, or segment matching.
Add a custom test adapter — GrowthBook provides test utilities natively.
Decision Log
Date
Decision
Reason
Owner
2026-05-26
Synchronous evaluate() after bootstrap()
Prevents async rendering waterfalls and hydration mismatches
David Holmes
2026-05-26
Generic TFlags parameter for typed flag names
Compile-time safety catches typos and stale flag references
David Holmes
2026-05-26
React helpers as optional exports, not required
Keeps the core interface framework-agnostic
David Holmes
2026-05-26
GrowthBook recommended as the default feature flags adapter
Not yet in ADR-027; open-source self-hosted fits platform philosophy. ADR-027 supplement needed to formalize.
David Holmes
2026-06-02
Reframed per ADR-014 (Open Source First): adopt @growthbook/growthbook as thin re-export rather than building a custom provider interface. Library API is the interface.
ADR-014 establishes that community libraries should be adopted directly; custom abstractions add maintenance cost without proportional value.
David Holmes
Document History
Date
Author
Change
2026-05-26
David Holmes
Initial draft
2026-06-02
David Holmes
Reframed per ADR-014: ship as thin re-export of @growthbook/growthbook, drop custom interface.