configcat-js

Official JavaScript SDK for evaluating ConfigCat feature flags and remote config values directly in the browser.

SDK
npm
v9.6.1
34stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
54/100Fair
Development Activity60
Maintenance56
Community28
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture78
Code Quality80
Innovation68
Learning Curve70

configcat-js is ConfigCat’s official client SDK for frontend JavaScript applications, giving browser-based apps a way to fetch, cache, and evaluate feature flags, A/B test variants, and remote configuration values without redeploying code. It wraps configcat-common, the shared cross-platform ConfigCat core, with two browser-specific pieces: an XMLHttpRequest-based config fetcher and a localStorage-backed cache, so all polling, evaluation, and targeting logic stays identical across ConfigCat’s SDKs while only the I/O layer changes per platform.

Apps call configcat.getClient(sdkKey) once to get a shared client instance, then client.getValueAsync(key, defaultValue, user?) to resolve a flag or config value, optionally targeting a specific user via ConfigCat’s percentage and targeting rules. It ships as both an npm package (CJS and ESM builds) and a CDN-ready UMD bundle on jsDelivr for script-tag usage without a build step. The maintainers have since released a consolidated js-unified-sdk and marked this package as no longer receiving security patches, so it remains a stable but legacy option for existing integrations.

What You Get

  • A getClient(sdkKey, pollingMode, options) factory that returns a singleton, shared client per SDK key across an app.
  • Three polling strategies from configcat-common (AutoPoll, LazyLoad, ManualPoll) selectable per client.
  • Async flag/config evaluation via getValueAsync(key, defaultValue, user?) with optional per-user targeting.
  • An XMLHttpRequest-based HttpConfigFetcher that forwards ETags via a ccetag query param for CDNs without automatic conditional-request handling.
  • A LocalStorageCache that persists the last-fetched config as UTF-8-safe base64, disabling itself gracefully when storage is unavailable (private browsing, quota limits).
  • A prebuilt CDN/UMD bundle (configcat.min.js) published to jsDelivr for script-tag usage with no bundler.

Common Use Cases

  • Gradually rolling out a new UI behind a flag and dialing up the release percentage from the ConfigCat dashboard without a frontend redeploy.
  • Running A/B tests and soft launches driven entirely by dashboard-configured targeting and percentage rules, evaluated client-side.
  • Passing the logged-in user into getValueAsync() in a React or Angular SPA so plan tier or beta cohort determines which flags are active.
  • Loading feature flags in static HTML/CDN-only sites via the jsDelivr <script> tag with no build tooling.

Under The Hood

Architecture configcat-js is a thin platform adapter over configcat-common, which owns all feature-flag evaluation, polling, and targeting logic. The package’s own src/ (index.ts, ConfigFetcher.ts, Cache.ts, Version.ts) implements exactly two interfaces defined by configcat-common: IConfigFetcher, via HttpConfigFetcher using the browser’s native XMLHttpRequest, and IConfigCatCache, via LocalStorageCache reading/writing window.localStorage. getClient() wires both into getClientCommon() from configcat-common and returns a singleton client per SDK key. Because this SDK does nothing but satisfy those two interfaces, any change to configcat-common’s core contracts would break it immediately — a clean but tightly coupled dependency-inversion boundary between shared logic and browser-specific I/O.

Tech Stack Written in TypeScript against configcat-common (pinned to 9.4.1) and tslib, with no other runtime dependencies — deliberately dependency-light to keep bundle size small. It builds to both CJS and ESM via separate tsc passes (tsconfig.build.cjs.json / tsconfig.build.esm.json) plus a Gulp step, and separately to a browser UMD bundle via Webpack (webpack.config.js) for CDN delivery through jsDelivr. Linting runs through ESLint with the TypeScript parser.

Code Quality Tests run under Karma against real Chrome, Chromium, and Firefox launchers (not just jsdom), asserted with Mocha and Chai, and instrumented for coverage via an Istanbul webpack loader uploaded to Codecov — a meaningfully stronger signal for a browser-only SDK than typical unit tests, since it exercises real XMLHttpRequest and localStorage behavior. Error handling is explicit: HttpConfigFetcher wraps XHR failures into typed FetchError reasons (timeout/abort/failure), and LocalStorageCache.getLocalStorage() deliberately no-ops when storage is disabled rather than throwing. CI runs a browser matrix (Chrome stable/beta, Firefox latest/beta/an older pinned version) on a daily cron to catch browser-behavior drift, alongside Snyk and SonarCloud badges for ongoing monitoring.

API Design getClient() memoizes one client per SDK key, so calling it from multiple places in an app can’t accidentally spin up duplicate pollers. The public surface is a small, async/await-first API — one call to get a client, one call to get a value, an optional User object for targeting — with sensible defaults (AutoPoll unless another mode is specified). It’s a standard SDK-wrapper pattern rather than a novel one, and the maintainers have already moved active development to a consolidated js-unified-sdk, leaving this package in legacy/maintenance mode.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search