npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@guidelytech/flags

v0.8.0

Published

Guidely feature flags and experiments for TypeScript: browsers, Node.js, Next.js, edge runtimes

Readme

@guidelytech/flags

Guidely feature flags, remote config and experiments for TypeScript. One client for browsers, Node.js ≥ 18, Next.js (server and edge), Deno, Bun and React Native; no runtime dependencies.

If you already use a Guidely SDK (@guidelytech/react, nextjs, react-native, svelte, sveltekit, sdk-core or the script tag), flags are built in: guidely.flags, useFlag(), flag()… with identity, page and device attributes filled in for you. Use this package directly for servers, edge functions and flags-only apps.

pnpm add @guidelytech/flags

Keys

  • Public key pk_… — the environment key you already use as projectId for tracking. Works everywhere, with no other configuration.
  • Secret key gly_sk_… (scope flags:read, servers only) — also needs environment. Gets server-only flags, and works when the environment hides its rules from public keys.

Browser

import { createFlagsClient } from "@guidelytech/flags";

const flags = createFlagsClient({
  sdkKey: "pk_prod_…",
  apiUrl: "https://guidelytech.com",
  attributes: { id: user.id, plan: user.plan, account: { id: org.id } },
});

await flags.ready();
if (flags.isEnabled("new-checkout")) showNewCheckout();
const color = flags.getString("checkout-button-color", "blue");
flags.subscribe(() => render()); // payload, attribute or override changes
flags.updateAttributes({ plan: "enterprise" });

The last payload is kept in localStorage, so returning visitors get flags instantly and offline.

Node.js / server

One client per process; evaluate per request with forUser() (it never changes the client):

import { createFlagsClient } from "@guidelytech/flags";

export const flags = createFlagsClient({ sdkKey: process.env.GUIDELY_SDK_KEY!, environment: "production" });

app.get("/checkout", async (req, res) => {
  await flags.ready(); // resolves once, after the first download (or failure)
  const f = flags.forUser({ id: req.user.id, plan: req.user.plan });
  res.render("checkout", { newCheckout: f.isEnabled("new-checkout"), limits: f.getJson("limits", {}) });
});

Next.js

Use @guidelytech/nextjs/server (getFlags(), getFlagsBootstrap()): it keeps one client across requests and hot reloads and bypasses the Next.js fetch cache. Pass getFlagsBootstrap() to the browser provider to render the same values on the server and the client.

Edge runtimes and serverless

Instances are short-lived, so don't poll — refresh on read once the cache is stale:

const flags = createFlagsClient({ sdkKey: "pk_prod_…", pollingMode: "lazy", cacheTtlSeconds: 30 });

API

| | | |---|---| | ready() / isReady() | First load settled (bootstrap, network success or failure). Never rejects. | | isEnabled(key, fallback = false) | Boolean flags only: any other value gives fallback. | | getValue(key, fallback) | Value, or fallback when missing, null or of another JSON type. | | getString / getNumber / getBoolean / getJson | Typed getters with the same rule. | | getDetails(key, fallback) | Value plus reason, ruleId, variationId, experiment, usedFallback. | | getAll() | Every flag's value (records no exposures). | | forUser(attributes) | Getters for other attributes (merged over the client's). | | setAttributes / updateAttributes / getAttributes | Replace / merge / read the attributes. | | setOverrides(map \| null) | Local values (see overrideBehaviour). | | setOffline(bool) / refresh() | Pause network activity / fetch now. | | getPayload() | The payload (or remote results) to bootstrap a browser from server rendering. | | subscribe(listener) | Change notifications; returns unsubscribe (works with useSyncExternalStore). | | flush() / destroy() | Send usage now / stop timers and streams. |

Getters never throw and never block: before flags load (or if Guidely is unreachable) they return your fallback, and afterwards the last good payload.

Options

| Option | Default | | |---|---|---| | sdkKey (alias projectId) | — | pk_… or gly_sk_…. | | apiUrl | https://guidelytech.com | Your Guidely URL. | | environment | — | Required with gly_sk_ keys. | | attributes | {} | Default attributes. | | pollingMode | auto | auto (every pollIntervalSeconds, default 60), lazy (on read after cacheTtlSeconds), manual (refresh() only), stream (server-sent events, polling while disconnected). | | payload / remoteResults | — | Bootstrap: used immediately (ready at once). | | remoteEval | false | Evaluate on the server (POST /flags/evaluate) for environments that hide their rules. Switched on automatically when a public key gets remote_evaluation_required. Re-evaluates (debounced) when attributes change; results are cached per attribute set. | | decryptionKey | — | For encrypted payloads (AES-256-GCM via WebCrypto). | | overrides / overrideBehaviour | — / localOverRemote | localOnly (never fetch; overrides, then the bootstrap payload), localOverRemote (overrides win), remoteOverLocal (only for flags missing remotely). | | devOverrides | true | Read dev overrides from environment variables and test globals. | | enableUrlOverrides | false | Browser QA: ?guidely_flags=new-checkout:true,checkout-button-color:"green". | | stickyBucketService | — | InMemoryStickyBucketStore / LocalStorageStickyBucketStore: users keep their experiment variation. | | storage | localStorage in browsers | Any getItem/setItem store, sync or async (AsyncStorage). false disables. | | trackingCallback(experiment, result) | — | Once per (experiment, user, variation): send exposures to your analytics. | | trackExposures | true unless trackingCallback | Send exposures to Guidely for experiment results. | | reportUsage | true | Aggregated evaluation counts, at most every 60 s (sendBeacon on page hide). | | onReady, onChange, onFlagEvaluated, onError | — | Hooks. | | offline, fetch, logger, now | — | Start offline; custom fetch; null silences logs; clock for tests. |

createStaticFlags({ payload, attributes }) gives the same getters over a payload with no network or tracking — framework bindings use it to server-render and hydrate.

Dev overrides (CI and tests)

Pin flag values without touching the app. Every client reads these once, when it is created:

| Source | Example | |---|---| | GUIDELY_FLAG_OVERRIDES | new-checkout:true,limit:5,theme:"dark" or {"new-checkout":true} | | GUIDELY_FLAG_OVERRIDES_FILE | path to a file holding the same text (JSON object or one key:value per line) | | GUIDELY_FLAG_OVERRIDE_BEHAVIOUR | localOnly — no network, no cached payload: hermetic tests | | globalThis.__GUIDELY_FLAG_OVERRIDES__ / __GUIDELY_FLAG_OVERRIDE_BEHAVIOUR__ | an object or the same text, set by a test runner in the page |

GUIDELY_FLAG_OVERRIDES='new-checkout:true' GUIDELY_FLAG_OVERRIDE_BEHAVIOUR=localOnly pnpm test
GUIDELY_FLAG_OVERRIDES_FILE=ci/flags.json pnpm test

A sample ci/flags.json (keys are flag keys; give each value the flag's type, since a value of the wrong type or null makes the getter return its fallback):

{
  "new-checkout": true,
  "checkout-button-color": "green",
  "max-cart-items": 25,
  "pricing-page": { "layout": "grid", "plans": ["starter", "pro", "team"] },
  "holiday-banner": null
}
// Playwright: set before the page's scripts run.
await page.addInitScript(() => {
  (window as any).__GUIDELY_FLAG_OVERRIDES__ = { "new-checkout": true };
});
// Cypress: cy.visit("/", { onBeforeLoad: (win) => { win.__GUIDELY_FLAG_OVERRIDES__ = { "new-checkout": true }; } });

Per flag, later wins: overrides / setOverrides() → file → variable → global → ?guidely_flags=. setOverrides() only replaces the first. Values are served with reason OVERRIDE. The client logs one warning listing the sources in use, so a variable left set in production shows up in logs; malformed sources go to onError and are ignored. devOverrides: false turns it all off.

With server rendering, set both: the variable for server code and the global for the browser (React and Svelte server renders read the bootstrap payload, which carries no overrides). parseOverrides(text) is exported for reading the same format elsewhere.

CLI

# In CI on your main branch: upload where each flag is used in code (shown on the flag's page).
npx guidely-flags code-refs --key "$GUIDELY_API_KEY" --environment production --repo acme/web

# Debug an evaluation.
npx guidely-flags evaluate --key pk_prod_… --flag new-checkout --attributes '{"id":"u1","plan":"pro"}'

code-refs needs a gly_sk_ key with flags:read and flags:code-refs. It scans files from git ls-files (or a walk skipping node_modules, dist, build, vendor…) under 1 MB for flag keys written as quoted string literals, and uploads { repo, branch, commit, refs }. Branch and commit default to the current git checkout (or GITHUB_REF_NAME / GITHUB_SHA). --dry-run prints the references instead. guidely-flags --help lists every option.

The evaluation semantics are specified in docs/feature-flags-spec.md.