@flagsman/sdk-js
@flagsman/sdk-js
Flagsman feature-flags SDK for the browser and React. Zero runtime
dependencies. ETag-cached resolve, live updates over SSE (with a polling
fallback), a localStorage last-good cache for instant/offline boot, and
batched exposure/goal analytics (via sendBeacon/keepalive).
Authenticates with a public client-side SDK key (flags-client-…). The key
alone determines org/project/environment — you never pass env or project.
Install
npm install @flagsman/sdk-js
Quickstart (vanilla browser)
import { createFlags } from '@flagsman/sdk-js';
const flags = createFlags({
clientKey: 'flags-client-xxxxxxxx',
baseUrl: 'https://flags.yourapp.com', // default http://localhost:8080
subject: currentUser?.id, // optional; an anon id is used otherwise
});
// Values are available synchronously (defaults / cache), and update live.
if (flags.boolVariation('new-checkout', false)) {
renderNewCheckout();
}
const heroColor = flags.stringVariation('hero-color', '#000');
const limit = flags.numberVariation('upload-limit', 10);
const layout = flags.jsonVariation<{ cols: number }>('grid', { cols: 3 });
// Full detail (value + variant + reason)
const { value, variant, reason } = flags.variationDetail('pricing-copy', 'control');
// Await the first resolve when you must (bootstrap resolves immediately).
await flags.ready();
// Report an experiment goal conversion (optionally with a metric value).
flags.track('purchase', 49.99);
// React to remote changes.
const unsubscribe = flags.onChange(() => rerender());
// Re-resolve for a new identity (e.g. after login).
await flags.identify({ subject: user.id, attrs: { plan: 'pro' } });
Exposure events for experiment flags are recorded automatically the first time
you read the flag (batched + deduped), so track() conversions can be
attributed to the arm the user actually saw.
React
import { FlagsProvider, useFlag, useValue, useVariationDetail, Flag } from '@flagsman/sdk-js/react';
function Root() {
return (
<FlagsProvider config={{ clientKey: 'flags-client-xxxxxxxx', subject: user.id }}>
<App />
</FlagsProvider>
);
}
function App() {
const showBeta = useFlag('beta-banner'); // boolean
const color = useValue<string>('hero-color', '#000');
const { value, variant, reason } = useVariationDetail('pricing-copy', 'control');
return (
<>
{showBeta && <BetaBanner />}
<Hero color={color} />
<Flag name="new-footer" fallback={<OldFooter />}>
<NewFooter />
</Flag>
</>
);
}
Components re-render automatically when flags change. FlagsProvider accepts
either a config (it creates and owns the client) or an existing client.
Available hooks: useFlag(key, fallback?), useVariant(key),
useValue(key, fallback?), useVariationDetail(key, fallback?),
useFlagsClient().
SSR / edge bootstrap
Resolve on the server and hand the result to the client to avoid a first-render flash:
import { resolveFlags } from '@flagsman/sdk-js';
const bootstrap = await resolveFlags(
{ clientKey: 'flags-client-xxxxxxxx', baseUrl },
{ subject: user.id },
);
// …serialize `bootstrap` into the page, then on the client:
const flags = createFlags({ clientKey, subject: user.id, bootstrap });
Client API
| Method | Returns |
|---|---|
init() / ready() |
Promise<void> — first resolve lifecycle |
isReady() |
boolean |
variation(key, default?) |
the served value |
variationDetail(key, default?) |
{ value, variant?, reason? } |
boolVariation(key, default?) |
boolean |
stringVariation(key, default?) |
string |
numberVariation(key, default?) |
number |
jsonVariation(key, default?) |
JSON value |
variant(key) |
string | undefined |
allFlags() |
Record<string, ResolvedFlag> |
identify(context) |
Promise<void> — re-resolve for a new subject/attrs |
track(goal, metricValue?) |
void — buffer a goal event |
onChange(cb) |
Unsubscribe |
close() |
void — flush + tear down |
FlagContext = { subject?, country?, server?, attrs? }.
Configuration (FlagsConfig)
clientKey (required), baseUrl, subject, country, server, attrs,
defaults, bootstrap, realtime (SSE, default on), pollMs, storageKey,
fetchImpl, onError, release, anonymousId, autoAttributes,
autoExposures, fetchTimeoutMs, explain, onExposure.
License
MIT