Web quickstart
In a few minutes your website will read a real feature flag — with a durable cache, a fail-safe answer for every situation, and nothing for you to manage in the browser.
Zero runtime dependencies; the whole SDK rides under a 10 kB gzip ceiling.
1. Install
Section titled “1. Install”The SDK lives in a public repository on GitHub — install it straight from there, pinned to the release:
npm install github:FortressFlag/FortressFlag_SDK_web#v1.0.0The package builds itself on install, and the import below is its entry point.
2. Start the SDK
Section titled “2. Start the SDK”Once, early in your page or app bootstrap:
import { Environment, FortressFlag } from "@fortressflag/sdk-web";
FortressFlag.start({ sdkKey: "ffc_prod_…", // from your project's SDK keys screen environment: Environment.PRODUCTION,});start returns immediately; cached values from previous visits are available right away,
and fresh values arrive in the background. The key is a client key — it’s
visible in your page source by design.
3. Read a flag
Section titled “3. Read a flag”if (FortressFlag.isEnabled("new-checkout", false)) { // render the new checkout}stringValue and numberValue read multivariate flags the same way, and
FortressFlag.onChange tells you when values move so you can re-render.
That’s it — your flag is live. Toggle it in the dashboard and open the page again (or wait out a poll) to watch it follow.
Nothing here ever throws
Section titled “Nothing here ever throws”No call in this API throws, and no promise from it rejects. Every read resolves through the
cascade: the freshest fetched value, then the last value this browser recorded, then your
default, then false. A FortressFlag outage, a dead network, an ad blocker, a revoked key —
all of them resolve to a flag value, none of them reach your code as an error.
(That ad-blocker case is real: some privacy extensions block flag requests. Cached values keep serving, and a browser that never fetched serves your defaults — “flags don’t update with uBlock on” is the cascade working, not a bug.)
What lives in the browser, honestly
Section titled “What lives in the browser, honestly”- The device identity lives in
localStorage, scoped to your origin. It’s random-minted and pseudonymous — and readable by your page’s own JavaScript, the same class of value as the SDK key beside it. - Private windows mint throwaway identities. Each private session counts as a device while it lasts; a user clearing site data is a new device too. And one person on your website, iOS app, and Android app is up to three devices — there’s no cross-platform linkage, by design.
- Your test suites are free. Browsers driven by Playwright, Selenium, Puppeteer, or
Cypress declare themselves, and the SDK mints a
sim_identity there: served flags, never billed. - Version tags don’t exist on web. The SDK sends
platformandsdkVersionautomatically, but there’s no reliableappVersionorosVersionfor a page — a targeting rule on those simply never matches a browser.
Where to next
Section titled “Where to next”- How flags reach your app — polling and the cache
- Device identity and billing — the identity in that storage key
- Targeting — rules, segments, and rollouts