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

@ops-ai/react-router-toggly

v1.2.1

Published

Toggly feature flags for React Router 7/8 framework mode (client + server)

Readme

@ops-ai/react-router-toggly

Toggly feature flags for React Router 7/8 framework mode. One package with ./client and ./server entry points. Core evaluation and telemetry live in-source (not published as a separate package).

Migrating from @ops-ai/remix-toggly-*? Those packages are deprecated. Install @ops-ai/react-router-toggly and import from /client and /server.

Browser telemetry

TogglyProvider and RouterTogglyProvider each own one compact browser reporter. With an app key, telemetry is enabled by default. Access explicit events through useToggly() or useTogglyContext():

const toggly = useToggly()
// Call these from application actions or an explicit view event.
toggly.recordUsage('Checkout')
toggly.recordView('Checkout', 'control')
toggly.incrementCounter('orders', 2)
toggly.setGauge('cartSize', 3)
await toggly.flushTelemetry()

Usage and view variants default to enabled; labels contain 1–64 ASCII letters, digits, underscores or hyphens. Counters sum nonnegative integer deltas, and gauges retain the latest finite nonnegative value. A single value cannot exceed 1,000,000. Metrics are app-level and contain no feature attribution.

Automatic checks record each evaluated feature after local and entity gates, before negation. Short-circuited keys do not count. Direct cached reads, hooks and components count actual evaluations; hydration and refresh snapshots alone do not. Rendering never implicitly records usage or views. Boolean A/B helpers use enabled/disabled check labels; explicit events may specify a variant label.

Provider config accepts enableTelemetry (default true), metricsBaseUrl (default https://metrics.toggly.io), and telemetryFlushIntervalMs (30000–60000 ms, default 45000). Set enableTelemetry: false to disable browser telemetry. enableUsageTracking: false disables checks/usage/views, and enableMetrics: false disables business metrics. Invalid intervals use the default. Invalid collector URLs disable telemetry without changing feature results; use absolute HTTP(S) URLs without credentials, query or fragment.

SSR/build, keyless and opted-out providers create no frontend reporter resources. Payloads contain app/environment, optional i (host-minted instance token) or u (client identity), feature/variant counts and numeric metrics. Claims, groups, entity data and timestamps are excluded. Requests omit credentials, use native gzip when available, and have bounded buffers, timeout and retries. Page hiding and unmount trigger a bounded best-effort flush; await flushTelemetry() to wait for the current best-effort attempt before navigation; it does not guarantee server acknowledgement.

Set config.instanceId to a token minted by your trusted host. It takes precedence over client identity/groups/claims in browser definition requests and telemetry. Rotate it with await context.identify(identity, {instanceId}); identify(identity) clears the token and uses client targeting. reset() clears identity and token. Groups/claims can be updated through the existing identify context. Changed provider groups/claims commit to the same owner, clear prior results to defaults, and become active on the next existing refresh trigger; they do not start an extra request. Omitted groups/claims clear those fields. Equivalent props preserve context explicitly set by identify. Failed context refreshes retain the new targeting scope with configured defaults; old results and pending responses cannot cross that boundary. Context changes preserve already queued events under their original attribution.

Each mounted provider is independent. App/environment replacement releases the old reporter without relabeling its queue (incompatible collector/transport or opt-out replacement discards pending old data), and ignores loader snapshots explicitly labeled for another owner. StrictMode effect replay preserves the committed owner; real unmount releases it and remount creates a fresh one. Browser telemetry does not change trusted server loader/action metrics or their existing APIs.

Install

npm install @ops-ai/react-router-toggly react-router react react-dom

Peers: react-router ^7 || ^8, react / react-dom ^18 || ^19. Optional: @react-router/node. Requires Node >=18.

Quick start

Server loader

// app/toggly.server.ts
import { createTogglyLoader } from '@ops-ai/react-router-toggly/server';

export const toggly = createTogglyLoader({
  appKey: process.env.TOGGLY_APP_KEY!,
  environment: process.env.TOGGLY_ENVIRONMENT ?? 'Production',
  getIdentity: async (request) => {
    // Resolve session identity for this request
    return null;
  },
});
// app/root.tsx
import { Outlet } from 'react-router';
import { RouterTogglyProvider } from '@ops-ai/react-router-toggly/client';
import { toggly } from './toggly.server';

export async function loader(args: { request: Request }) {
  return toggly.getLoaderData(args);
}

export default function App() {
  return (
    <RouterTogglyProvider routeId="root">
      <Outlet />
    </RouterTogglyProvider>
  );
}

Client gates

import { Feature, useFeature } from '@ops-ai/react-router-toggly/client';

export default function Home() {
  const beta = useFeature('Beta');
  return (
    <Feature feature="Checkout">
      <Checkout />
      {beta ? <BetaBanner /> : null}
    </Feature>
  );
}

Feature-gated actions

import { createFeatureGatedAction } from '@ops-ai/react-router-toggly/server';

export const action = createFeatureGatedAction(
  {
    appKey: process.env.TOGGLY_APP_KEY!,
    requiredFeatures: 'AdminTools',
  },
  async () => ({ ok: true }),
);

Exports

| Subpath | Purpose | |---------|---------| | @ops-ai/react-router-toggly/client | RouterTogglyProvider, hooks, Feature components | | @ops-ai/react-router-toggly/server | Loaders, actions, TogglyServerClient |

Server-only modules (ws, gRPC telemetry) must not be imported from client code.

Development

npm install
npm run build
npm test
npm run test:coverage
npm run test:hosts   # packed RR7/RR8 hosts (needs matching Node majors)

License

MIT