OpenFeature LocalStorage Provider
An OpenFeature provider that resolves feature flags from the browser's localStorage for instant client-side overrides.
Repository Health
Technical Analysis
The LocalStorage Provider is an OpenFeature Provider implementation backed entirely by the browser’s localStorage, requiring no server infrastructure to set up or manage. It lets anyone with access to browser developer tools override feature flag values for their own session, casting stored string values to booleans, strings, numbers, or objects as each flag is resolved.
It’s designed to be composed with a ‘real’ remote provider (typically via OpenFeature’s MultiProvider) so that local overrides take precedence during development, QA, or support debugging, while production traffic still resolves through the primary provider. Built-in setFlags, clearFlags, and getFlags helper methods manage the underlying storage entries and emit ConfigurationChanged events so OpenFeature clients pick up changes immediately, without requiring a page refresh.
What You Get
- A
LocalStorageProviderclass implementing the OpenFeatureProviderinterface forresolveBooleanEvaluation,resolveStringEvaluation,resolveNumberEvaluation, andresolveObjectEvaluation - Automatic value casting from raw localStorage strings to booleans, numbers, and parsed JSON objects, with typed
ParseError/FlagNotFoundErrorfailures when a value can’t be resolved - A configurable
prefixoption (defaultopenfeature.) to namespace flag keys and avoid collisions with other localStorage data setFlags/clearFlags/getFlagsmethods for programmatically managing stored flag values, including automaticConfigurationChangedevent emission- Safe no-op behavior (
FlagNotFoundErrorinstead of a crash) in environments wherelocalStorageis undefined, such as server-side rendering
Common Use Cases
- Layering local flag overrides on top of a remote provider (e.g. flagd, LaunchDarkly) via OpenFeature’s
MultiProvider, so QA/support can flip a flag for just their own browser - Building a hidden debug UI that lets developers or product managers self-serve access to in-development features without a backend flag service
- Local development and demos where a full feature-flag backend isn’t available or necessary
- Deterministic end-to-end/UI tests that need to pin a flag to a specific value per test run by pre-seeding localStorage
Under The Hood
Architecture
The package exposes a single LocalStorageProvider class (src/lib/localstorage-provider.ts) implementing the OpenFeature Provider interface from @openfeature/web-sdk. The four resolveXEvaluation methods each delegate to a private evaluateLocalStorage helper that reads a prefixed key from localStorage, applies a type-specific parse callback, and normalizes failures into the SDK’s FlagNotFoundError/ParseError types. Mutating methods (setFlags, clearFlags) write back to localStorage and emit ConfigurationChanged through an OpenFeatureEventEmitter, matching the observer pattern OpenFeature clients rely on for live flag updates. Everything is synchronous and browser-scoped (runsOn: 'client') — there’s no network or filesystem I/O, so the provider class itself is the only real architectural layer.
Tech Stack
Distributed as a single npm package with one runtime dependency (tslib) and a peer dependency on @openfeature/web-sdk (^1.6.0). It lives inside the open-feature/js-sdk-contrib Nx monorepo alongside sibling providers and hooks, compiled with TypeScript and tested with Jest via Babel transforms, linted with ESLint. It ships as a plain browser-consumable package with no server runtime, database, or build-time code generation of its own.
Code Quality
The accompanying spec file is thorough for the package’s scope: it exercises all four resolve methods, the default/custom/empty prefix option, setFlags/clearFlags/getFlags, event emission, and explicit SSR-style “no localStorage” edge cases via a dedicated mock helper. Errors are typed and rethrown rather than swallowed, and the private evaluateLocalStorage helper centralizes exception normalization so each public method stays simple. Fully typed in TypeScript, with the exported Config type documented via JSDoc.
API Design
The public surface is deliberately small: construct with an optional prefix, register via OpenFeature.setProvider (typically wrapped in a MultiProvider), then call standard OpenFeature client methods — no bespoke API to learn beyond the constructor option and the setFlags/clearFlags/getFlags helper trio. The README documents every supported value type with a runnable example, keeping onboarding to a few minutes. Because it strictly implements the OpenFeature Provider contract, the design trades novelty for predictability — it behaves exactly like any other OpenFeature provider, which is the point.