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

@togglebox/sdk-nextjs

v0.1.0

Published

Next.js SDK for remote config service

Readme

@togglebox/sdk-nextjs

Next.js SDK for ToggleBox - Remote configuration, feature flags, and A/B experiments.

Installation

npm install @togglebox/sdk-nextjs
# or
pnpm add @togglebox/sdk-nextjs

Quick Start

Client Components (Hooks)

// app/providers.tsx
"use client";

import { ToggleBoxProvider } from "@togglebox/sdk-nextjs";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ToggleBoxProvider
      platform="web"
      environment="staging"
      apiUrl={process.env.NEXT_PUBLIC_TOGGLEBOX_API_URL!}
      apiKey={process.env.NEXT_PUBLIC_TOGGLEBOX_API_KEY} // Optional
    >
      {children}
    </ToggleBoxProvider>
  );
}
// app/layout.tsx
import { Providers } from "./providers";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Server Components

// app/page.tsx
import {
  getConfig,
  getFlag,
  getExperiment,
} from "@togglebox/sdk-nextjs/server";

const serverOptions = {
  platform: "web",
  environment: "staging",
  apiUrl: process.env.TOGGLEBOX_API_URL!,
  apiKey: process.env.TOGGLEBOX_API_KEY, // Optional
};

export default async function Page() {
  const [
    { config, getConfigValue },
    { enabled: darkModeEnabled },
    { variant },
  ] = await Promise.all([
    getConfig(serverOptions),
    getFlag("dark-mode", { userId: "user-123" }, serverOptions),
    getExperiment("checkout-test", { userId: "user-123" }, serverOptions),
  ]);

  const theme = getConfigValue("theme", "light");

  return (
    <div className={darkModeEnabled ? "dark" : "light"}>
      <h1>Theme: {theme}</h1>
      <p>Variant: {variant?.variationKey}</p>
    </div>
  );
}

Three-Tier Architecture

| Tier | Feature | Client Hook | Server Function | | ---- | ----------------- | ------------------ | ------------------ | | 1 | Remote Configs | useConfig() | getConfig() | | 2 | Feature Flags | useFlags() | getFlags() | | 2 | Single Flag | useFlag() | getFlag() | | 3 | Experiments | useExperiments() | getExperiments() | | 3 | Single Experiment | useExperiment() | getExperiment() | | - | Analytics | useAnalytics() | getAnalytics() |

Client Hooks API

Import from @togglebox/sdk-nextjs:

useConfig

const { config, getConfigValue, isLoading, error, refresh } = useConfig();

// Get typed config value with default
const theme = await getConfigValue("theme", "light");
const maxRetries = await getConfigValue<number>("max_retries", 3);

useFlags

const { flags, isFlagEnabled, isLoading, error, refresh } = useFlags();

// Check if a flag is enabled for a user
const enabled = await isFlagEnabled("new-checkout", { userId: "user-123" });

useFlag

const { flag, exists, isLoading, checkEnabled } = useFlag("dark-mode", {
  userId,
});

// Check if enabled
const enabled = await checkEnabled();

useExperiments

const { experiments, getVariant, isLoading, error, refresh } = useExperiments();

// Get variant assignment (returns variationKey string or null)
const variant = await getVariant("checkout-test", { userId: "user-123" });
console.log(variant); // "control", "variant_1", etc.

useExperiment

const { experiment, exists, isLoading, getVariant } = useExperiment(
  "checkout-test",
  { userId },
);

// Get assigned variant (returns variationKey string or null)
const variant = await getVariant();
console.log(variant); // "control", "variant_1", etc.

useAnalytics

const { trackEvent, trackConversion, flushStats } = useAnalytics();

// Track custom event
trackEvent("button_click", { userId }, { properties: { button: "checkout" } });

// Track conversion for experiment
await trackConversion(
  "checkout-test",
  { userId },
  {
    metricName: "purchase",
    value: 99.99,
  },
);

// Flush pending stats
await flushStats();

Server Functions API

Import from @togglebox/sdk-nextjs/server:

getConfig

const { config, getConfigValue } = await getConfig(serverOptions);

const theme = getConfigValue("theme", "light");

getFlags

const { flags, isFlagEnabled } = await getFlags(serverOptions);

const enabled = isFlagEnabled("new-checkout", { userId: "user-123" });

getFlag

const { flag, exists, enabled } = await getFlag(
  "dark-mode",
  { userId: "user-123" },
  serverOptions,
);

if (enabled) {
  // Show dark mode
}

getExperiments

const { experiments, getVariant } = await getExperiments(serverOptions);

const variant = getVariant("checkout-test", { userId: "user-123" });

getExperiment

const { experiment, exists, variant } = await getExperiment(
  "checkout-test",
  { userId: "user-123" },
  serverOptions,
);

if (variant?.variationKey === "new-checkout") {
  // Show new checkout
}

getAnalytics

const { trackEvent, trackConversion, flushStats } =
  await getAnalytics(serverOptions);

await trackConversion(
  "checkout-test",
  { userId },
  { metricName: "purchase", value: 99.99 },
);
await flushStats(); // Always call to send events and cleanup

Provider Configuration

<ToggleBoxProvider
  // Required
  platform="web"
  environment="staging"
  // API Configuration (choose one)
  apiUrl="https://your-api.com/api/v1" // Self-hosted
  // OR
  tenantSubdomain="acme" // Cloud: https://acme.togglebox.dev
  // Optional
  apiKey="tb_live_xxxxx" // API key for authentication
  configVersion="stable" // "stable", "latest", or specific version
  // Caching
  cache={{
    enabled: true,
    ttl: 300000, // 5 minutes
  }}
  // Auto-refresh
  pollingInterval={60000} // Poll every minute (0 to disable)
  // SSR Hydration (from server fetch)
  initialConfig={serverConfig}
  initialFlags={serverFlags}
  initialExperiments={serverExperiments}
>
  {children}
</ToggleBoxProvider>

SSR with Hydration

Fetch data on the server and hydrate the client:

// app/layout.tsx
import {
  getConfig,
  getFlags,
  getExperiments,
} from "@togglebox/sdk-nextjs/server";
import { Providers } from "./providers";

const serverOptions = {
  platform: "web",
  environment: "staging",
  apiUrl: process.env.TOGGLEBOX_API_URL!,
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const [{ config }, { flags }, { experiments }] = await Promise.all([
    getConfig(serverOptions),
    getFlags(serverOptions),
    getExperiments(serverOptions),
  ]);

  return (
    <html>
      <body>
        <Providers
          initialConfig={config}
          initialFlags={flags}
          initialExperiments={experiments}
        >
          {children}
        </Providers>
      </body>
    </html>
  );
}

Examples

Feature Flag with Loading State

"use client";

import { useFlag } from "@togglebox/sdk-nextjs";
import { useEffect, useState } from "react";

function Dashboard() {
  const { isLoading, checkEnabled } = useFlag("new-dashboard");
  const [showNewUI, setShowNewUI] = useState(false);

  useEffect(() => {
    checkEnabled().then(setShowNewUI);
  }, [checkEnabled]);

  if (isLoading) return <Spinner />;

  return showNewUI ? <NewDashboard /> : <LegacyDashboard />;
}

Experiment with Conversion Tracking

"use client";

import { useExperiment, useAnalytics } from "@togglebox/sdk-nextjs";
import { useEffect, useState } from "react";

function CheckoutPage({ userId }: { userId: string }) {
  const { getVariant } = useExperiment("checkout-test", { userId });
  const { trackConversion, flushStats } = useAnalytics();
  const [variant, setVariant] = useState<string | null>(null);

  useEffect(() => {
    getVariant().then(setVariant);
  }, [getVariant]);

  const handlePurchase = async (amount: number) => {
    // Process payment...

    await trackConversion(
      "checkout-test",
      { userId },
      {
        metricName: "purchase",
        value: amount,
      },
    );
    await flushStats();
  };

  if (variant === "one-page")
    return <OnePageCheckout onPurchase={handlePurchase} />;
  if (variant === "express")
    return <ExpressCheckout onPurchase={handlePurchase} />;
  return <DefaultCheckout onPurchase={handlePurchase} />;
}

Manual Refresh

"use client";

import { useConfig } from "@togglebox/sdk-nextjs";

function RefreshButton() {
  const { refresh, isLoading } = useConfig();

  return (
    <button onClick={refresh} disabled={isLoading}>
      {isLoading ? "Refreshing..." : "Refresh Config"}
    </button>
  );
}

TypeScript

Full TypeScript support:

// Client imports
import {
  ToggleBoxProvider,
  useConfig,
  useFlags,
  useFlag,
  useExperiments,
  useExperiment,
  useAnalytics,
} from "@togglebox/sdk-nextjs";

// Server imports
import {
  getConfig,
  getFlags,
  getFlag,
  getExperiments,
  getExperiment,
  getAnalytics,
} from "@togglebox/sdk-nextjs/server";

// Types
import type {
  ToggleBoxProviderProps,
  UseConfigResult,
  UseFlagsResult,
  UseExperimentsResult,
  UseAnalyticsResult,
  Config,
  Flag,
  FlagContext,
  Experiment,
  ExperimentContext,
  VariantAssignment,
  ConversionData,
  EventData,
} from "@togglebox/sdk-nextjs";

import type {
  ServerOptions,
  ServerConfigResult,
  ServerFlagsResult,
  ServerFlagResult,
  ServerExperimentsResult,
  ServerExperimentResult,
  ServerAnalyticsResult,
} from "@togglebox/sdk-nextjs/server";

Requirements

  • Next.js 14+ (App Router)
  • React 18+ or 19+

License

MIT