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

@flagforge/sdk-react

v0.2.0

Published

FlagForge React SDK — Provider + hooks for feature flag evaluation with real-time updates

Readme

@flagforge/sdk-react

React SDK for FlagForge — a Provider plus hooks for feature flag evaluation with real-time updates.

Built on top of @flagforge/sdk-js.

Install

npm install @flagforge/sdk-react @flagforge/sdk-js
# or
pnpm add @flagforge/sdk-react @flagforge/sdk-js
# or
yarn add @flagforge/sdk-react @flagforge/sdk-js

Peer dependencies: React 17+, @flagforge/sdk-js >= 0.1.0

You also need a running FlagForge server and an SDK key for your environment.

Quick start (Next.js App Router)

1. Environment variables

Create .env.local:

NEXT_PUBLIC_FLAGFORGE_API_URL=http://localhost:8080
NEXT_PUBLIC_FLAGFORGE_CLIENT_KEY=cli_your_key_here

Use a client key (cli_...) in the browser. Never expose a server key (srv_...) in frontend code.

2. Provider (client component)

// components/flagforge-provider.tsx
"use client";

import { FlagForgeProvider } from "@flagforge/sdk-react";
import type { ReactNode } from "react";

export function AppFlagForgeProvider({ children }: { children: ReactNode }) {
  return (
    <FlagForgeProvider
      config={{
        clientKey: process.env.NEXT_PUBLIC_FLAGFORGE_CLIENT_KEY!,
        baseUrl: process.env.NEXT_PUBLIC_FLAGFORGE_API_URL!,
        streaming: false,
      }}
    >
      {children}
    </FlagForgeProvider>
  );
}

3. Wrap your app

// app/layout.tsx
import { AppFlagForgeProvider } from "@/components/flagforge-provider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <AppFlagForgeProvider>{children}</AppFlagForgeProvider>
      </body>
    </html>
  );
}

4. Use a flag

"use client";

import { useBooleanFlag } from "@flagforge/sdk-react";

export function CheckoutFeature() {
  const { value: enabled, loading, reason } = useBooleanFlag(
    "new-checkout",
    false,
    {
      targetingKey: "user-123",
      attributes: { plan: "pro", country: "US" },
    },
  );

  if (loading) return null;

  return enabled ? <div>New checkout enabled</div> : <div>Old checkout</div>;
}

API

<FlagForgeProvider>

Wraps your app and initializes the FlagForge client.

<FlagForgeProvider
  config={{
    clientKey: "cli_...",           // browser / untrusted environments
    // serverKey: "srv_...",        // Node.js only — do not use in browser
    baseUrl: "http://localhost:8080",
    streaming: false,               // client keys use remote evaluation
    pollingInterval: 30_000,
    heartbeatIntervalMs: 30_000,    // optional — connection tracking
    sdkInstanceId: "web-app-1",     // optional — stable instance id
    runtime: "browser",             // optional — sent with heartbeat
    context: {                      // optional default evaluation context
      targetingKey: "user-123",
      attributes: { plan: "pro" },
    },
  }}
  onReady={() => console.log("SDK ready")}
  onError={(err) => console.error(err)}
  onUpdate={(config) => console.log("Config updated", config.version)}
>
  {children}
</FlagForgeProvider>

| Prop | Type | Description | |------|------|-------------| | config | FlagForgeConfig (without lifecycle callbacks) | SDK configuration | | onReady | () => void | Called when initial config is loaded | | onError | (error: Error) => void | Called on SDK errors | | onUpdate | (config: FlagsConfig) => void | Called when flag config changes | | children | ReactNode | App content |

Hooks

All flag hooks return { value, reason, loading }.

| Hook | Signature | Description | |------|-----------|-------------| | useBooleanFlag | (key, defaultValue, context?) | Boolean flag | | useStringFlag | (key, defaultValue, context?) | String flag | | useNumberFlag | (key, defaultValue, context?) | Number flag | | useJsonFlag | (key, defaultValue, context?) | JSON flag | | useFlag | (key, defaultValue?, context?) | Generic / unknown value | | useFlagForge | () | Access { client, isReady, error, updateCount } |

Evaluation context (optional third argument):

{
  targetingKey?: string;              // user id for overrides / rollouts
  attributes?: Record<string, unknown>; // e.g. plan, country, version
}

Example: typed hooks

"use client";

import {
  useBooleanFlag,
  useStringFlag,
  useNumberFlag,
  useJsonFlag,
} from "@flagforge/sdk-react";

function FeatureFlags() {
  const checkout = useBooleanFlag("new-checkout", false);
  const theme = useStringFlag("ui-theme", "light");
  const maxItems = useNumberFlag("cart-max-items", 10);
  const config = useJsonFlag<{ beta: boolean }>("experiments", { beta: false });

  // ...
}

Example: direct client access

"use client";

import { useFlagForge } from "@flagforge/sdk-react";

function Status() {
  const { isReady, error } = useFlagForge();

  if (error) return <p>FlagForge error: {error.message}</p>;
  if (!isReady) return <p>Loading flags…</p>;
  return <p>Flags ready</p>;
}

Client key vs server key

| Key type | Prefix | Where to use | Behavior | |----------|--------|--------------|----------| | Client | cli_ | Browser, React client components | Remote evaluation via API — targeting rules stay on the server | | Server | srv_ | Node.js, API routes, SSR | Downloads config + evaluates locally; never expose in frontend |

For Next.js:

  • Client componentsclientKey + NEXT_PUBLIC_* env vars
  • Server Components / Route Handlers → use @flagforge/sdk-js with serverKey (server-only env, no NEXT_PUBLIC_)

Plain React (Vite, CRA, etc.)

Same pattern: wrap your root with FlagForgeProvider and use hooks in child components. Any component using hooks must run on the client (no SSR hooks without a client boundary).

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { FlagForgeProvider } from "@flagforge/sdk-react";
import App from "./App";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <FlagForgeProvider
      config={{
        clientKey: import.meta.env.VITE_FLAGFORGE_CLIENT_KEY,
        baseUrl: import.meta.env.VITE_FLAGFORGE_API_URL,
      }}
    >
      <App />
    </FlagForgeProvider>
  </StrictMode>,
);

Troubleshooting

| Problem | Likely cause | |---------|----------------| | Hook throws “must be used within FlagForgeProvider” | Component is outside <FlagForgeProvider> | | Next.js error about hooks in Server Components | Add "use client" to the file | | Flag always returns default | Wrong flag key, API URL, or invalid SDK key | | HTTP 429 errors | Per-SDK-key rate limit — SDK retries automatically; reduce request volume | | Browser blocks requests | HTTPS site calling http:// API (mixed content) | | Full config visible in network tab with srv_ key | You used a server key in the browser — switch to cli_ |

Verify your API

curl -X POST http://localhost:8080/api/v1/evaluate \
  -H "Authorization: cli_your_key" \
  -H "Content-Type: application/json" \
  -d '{"flagKey":"new-checkout","context":{"targetingKey":"user-123"}}'

Related

License

MIT