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

@replanejs/react

v1.0.6

Published

React SDK for Replane - feature flags and remote configuration

Readme

Replane is a dynamic configuration manager that lets you tweak your software without running scripts or building your own admin panel. Store feature flags, rate limits, UI text, log level, rollout percentage, and more. Delegate editing to teammates and share config across services. No redeploys needed.

Why Dynamic Configuration?

  • Feature flags – toggle features, run A/B tests, roll out to user segments
  • Operational tuning – adjust limits, TTLs, and timeouts without redeploying
  • Per-environment settings – different values for production, staging, dev
  • Incident response – instantly revert to a known-good version
  • Cross-service configuration – share settings with realtime sync
  • Non-engineer access – safe editing with schema validation

Installation

npm install @replanejs/react
# or
pnpm add @replanejs/react
# or
yarn add @replanejs/react

Requirements

  • React 18.0.0 or higher
  • Node.js 18.0.0 or higher

Quick Start

import { ReplaneProvider, useConfig } from "@replanejs/react";

function App() {
  return (
    <ReplaneProvider
      connection={{
        baseUrl: "https://cloud.replane.dev", // or your self-hosted URL
        sdkKey: "your-sdk-key",
      }}
      loader={<div>Loading...</div>}
    >
      <MyComponent />
    </ReplaneProvider>
  );
}

function MyComponent() {
  const isFeatureEnabled = useConfig<boolean>("feature-flag-name");

  return <div>{isFeatureEnabled ? "Feature is enabled!" : "Feature is disabled"}</div>;
}

API

ReplaneProvider

Provider component that makes the Replane client available to your component tree. Supports multiple usage patterns:

1. With connection (recommended)

The provider creates and manages the client internally. Use an Error Boundary to handle initialization errors:

import { ErrorBoundary } from "react-error-boundary";

<ErrorBoundary fallback={<div>Failed to load configuration</div>}>
  <ReplaneProvider
    connection={{
      baseUrl: "https://your-replane-server.com",
      sdkKey: "your-sdk-key",
    }}
    loader={<LoadingSpinner />}
  >
    <App />
  </ReplaneProvider>
</ErrorBoundary>;

Provider Props

| Prop | Type | Required | Description | | ------------ | ------------------------- | -------- | ------------------------------------------------------------ | | connection | ConnectOptions \| null | Yes | Connection options (see below), or null to skip connection | | defaults | Record<string, unknown> | No | Default values if server is unavailable | | context | Record<string, unknown> | No | Default context for override evaluations | | snapshot | ReplaneSnapshot | No | Snapshot for SSR hydration | | logger | ReplaneLogger | No | Custom logger (default: console) | | loader | ReactNode | No | Component to show while loading | | suspense | boolean | No | Use React Suspense for loading state | | async | boolean | No | Connect asynchronously (renders immediately with defaults) |

Connection Options

The connection prop accepts the following options:

| Option | Type | Required | Description | | --------------------- | -------------- | -------- | ----------------------------------------- | | baseUrl | string | Yes | Replane server URL | | sdkKey | string | Yes | SDK key for authentication | | connectTimeoutMs | number | No | SDK connection timeout (default: 5000) | | requestTimeoutMs | number | No | Timeout for SSE requests (default: 2000) | | retryDelayMs | number | No | Base delay between retries (default: 200) | | inactivityTimeoutMs | number | No | SSE inactivity timeout (default: 30000) | | fetchFn | typeof fetch | No | Custom fetch implementation |

See @replanejs/sdk documentation for more details.

2. With pre-created client

Use this when you need more control over client lifecycle:

import { Replane } from "@replanejs/sdk";

const client = new Replane();
await client.connect({
  baseUrl: "https://your-replane-server.com",
  sdkKey: "your-sdk-key",
});

<ReplaneProvider client={client}>
  <App />
</ReplaneProvider>;

3. With Suspense

Integrates with React Suspense for loading states:

<ErrorBoundary fallback={<div>Failed to load configuration</div>}>
  <Suspense fallback={<LoadingSpinner />}>
    <ReplaneProvider
      connection={{
        baseUrl: "https://cloud.replane.dev", // or your self-hosted URL
        sdkKey: "your-sdk-key",
      }}
      suspense
    >
      <App />
    </ReplaneProvider>
  </Suspense>
</ErrorBoundary>

4. With async mode

Connect in the background while rendering immediately with defaults:

<ReplaneProvider
  connection={{
    baseUrl: "https://your-replane-server.com",
    sdkKey: "your-sdk-key",
  }}
  defaults={{ featureEnabled: false }}
  async
>
  <App />
</ReplaneProvider>

5. With snapshot (for SSR/hydration)

Restore a client from a snapshot obtained on the server. This is synchronous and useful for SSR scenarios:

// On the server
const serverClient = new Replane();
await serverClient.connect({ baseUrl: "...", sdkKey: "..." });
const snapshot = serverClient.getSnapshot();
// Pass snapshot to client via props, context, or serialized HTML

// On the client
<ReplaneProvider
  connection={{
    baseUrl: "https://your-replane-server.com",
    sdkKey: "your-sdk-key",
  }}
  snapshot={snapshot}
>
  <App />
</ReplaneProvider>;

The restored client is immediately available with no loading state. The provider will establish a connection for real-time updates in the background.

useConfig

Hook to retrieve a configuration value. Automatically subscribes to updates and re-renders when the value changes.

function MyComponent() {
  // Basic usage
  const theme = useConfig<string>("theme");

  // With evaluation context
  const discount = useConfig<number>("discount-percentage", {
    context: {
      userId: "123",
      isPremium: true,
    },
  });

  return (
    <div>
      Theme: {theme}, Discount: {discount}%
    </div>
  );
}

useReplane

Hook to access the underlying Replane client directly. Returns the client instance:

function MyComponent() {
  const replane = useReplane();

  const handleClick = () => {
    // Access replane methods directly
    const value = replane.get("some-config");
    console.log(value);
  };

  return <button onClick={handleClick}>Get Config</button>;
}

createReplaneHook

Factory function to create a typed version of useReplane. Returns a hook that provides the typed client directly:

import { createReplaneHook } from "@replanejs/react";

// Define your config types
interface AppConfigs {
  theme: { darkMode: boolean; primaryColor: string };
  features: { beta: boolean; analytics: boolean };
  maxItems: number;
}

// Create a typed hook
const useAppReplane = createReplaneHook<AppConfigs>();

function MyComponent() {
  const replane = useAppReplane();

  // replane.get is now typed - autocomplete works!
  const theme = replane.get("theme");
  //    ^? { darkMode: boolean; primaryColor: string }

  return <div>Dark mode: {theme.darkMode ? "on" : "off"}</div>;
}

createConfigHook

Factory function to create a typed version of useConfig. This provides autocomplete for config names and type inference for values:

import { createConfigHook } from "@replanejs/react";

// Define your config types
interface AppConfigs {
  theme: { darkMode: boolean; primaryColor: string };
  features: { beta: boolean; analytics: boolean };
  maxItems: number;
}

// Create a typed hook
const useAppConfig = createConfigHook<AppConfigs>();

function MyComponent() {
  // Autocomplete for config names, automatic type inference
  const theme = useAppConfig("theme");
  //    ^? { darkMode: boolean; primaryColor: string }

  const features = useAppConfig("features");
  //    ^? { beta: boolean; analytics: boolean }

  const maxItems = useAppConfig("maxItems");
  //    ^? number

  // With context override
  const premiumFeatures = useAppConfig("features", {
    context: { userId: "123", plan: "premium" },
  });

  return (
    <div>
      <p>Dark mode: {theme.darkMode ? "on" : "off"}</p>
      <p>Beta enabled: {features.beta ? "yes" : "no"}</p>
      <p>Max items: {maxItems}</p>
    </div>
  );
}

clearSuspenseCache

Utility function to clear the suspense cache. Useful for testing or forcing re-initialization:

import { clearSuspenseCache } from "@replanejs/react";

// Clear cache for specific options
clearSuspenseCache({
  baseUrl: "https://your-replane-server.com",
  sdkKey: "your-sdk-key",
});

// Clear entire cache
clearSuspenseCache();

TypeScript

The SDK is fully typed. For the best TypeScript experience, use the hook factory functions:

// Define all your config types in one interface
interface AppConfigs {
  "theme-config": {
    darkMode: boolean;
    primaryColor: string;
  };
  "feature-flags": {
    newUI: boolean;
    beta: boolean;
  };
  "max-items": number;
  "welcome-message": string;
}

// Create typed hooks once
const useAppReplane = createReplaneHook<AppConfigs>();
const useAppConfig = createConfigHook<AppConfigs>();

// Use throughout your app with full type safety
function Settings() {
  const theme = useAppConfig("theme-config");
  //    ^? { darkMode: boolean; primaryColor: string }

  const replane = useAppReplane();
  const snapshot = replane.getSnapshot();
  //    ^? { configs: ConfigSnapshot<AppConfigs>[] }

  return (
    <div style={{ color: theme.primaryColor }}>
      Dark mode: {theme.darkMode ? "enabled" : "disabled"}
    </div>
  );
}

Error Handling

The provider throws errors during rendering so they can be caught by React Error Boundaries:

import { Component, ReactNode } from "react";

class ErrorBoundary extends Component<
  { children: ReactNode; fallback: ReactNode },
  { hasError: boolean }
> {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback;
    }
    return this.props.children;
  }
}

// Usage
<ErrorBoundary fallback={<div>Configuration failed to load</div>}>
  <ReplaneProvider connection={connection} loader={<Loading />}>
    <App />
  </ReplaneProvider>
</ErrorBoundary>;

Or use a library like react-error-boundary:

import { ErrorBoundary } from "react-error-boundary";

<ErrorBoundary
  fallbackRender={({ error, resetErrorBoundary }) => (
    <div>
      <p>Error: {error.message}</p>
      <button onClick={resetErrorBoundary}>Retry</button>
    </div>
  )}
  onReset={() => clearSuspenseCache()}
>
  <ReplaneProvider connection={connection} loader={<Loading />}>
    <App />
  </ReplaneProvider>
</ErrorBoundary>;

Community

Have questions or want to discuss Replane? Join the conversation in GitHub Discussions.

License

MIT