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

@reopt-ai/data-sdk-devtool

v0.2.0

Published

reopt-data SDK devtools — records what the browser SDK sends and shows it in a floating panel; off in production by default

Readme

@reopt-ai/data-sdk-devtool

A devtools panel for the reopt-data browser SDK: sanitized batches the SDK sent, the identity lifecycle the browser is tracked under, and any tabs your app adds.

Off in production by default. createDevtools() follows NODE_ENV; a production bundle carries an inert instance — the page's own fetch, an empty store, a component that renders null. Pass enabled: true to force it on for a demo or a staging deployment.

Small when inactive. No CSS import, UI library, or React context. The ESM entry is a ~0.8 KB gzip gate and the React entry is ~0.4 KB; the CommonJS compatibility entries are also guarded by explicit budgets. When disabled they keep the page's transport, render null, and request no recorder or UI chunks. When enabled, the recorder and status bar load lazily; the expanded panel loads only on the first click.

| Entry | What | | ---------------------------------- | --------------------------------------------------------------------- | | @reopt-ai/data-sdk-devtool | createDevtools() — a recording fetch and the store. No framework. | | @reopt-ai/data-sdk-devtool/react | <ReoptDevtools />, useDevtoolsState()"use client" |

Install

pnpm add -D @reopt-ai/data-sdk-devtool

Peer: @reopt-ai/data-sdk-client (and react for the panel).

Use

// lib/devtools.ts — one instance, shared by the SDK config and the panel
import { createDevtools } from "@reopt-ai/data-sdk-devtool";

export const devtools = createDevtools();
// createDevtools({ enabled: true }) to show it in production as well
// the client boundary that creates the SDK client
"use client";
import { ReoptProvider } from "@reopt-ai/data-sdk-client/next";
import { ReoptDevtools } from "@reopt-ai/data-sdk-devtool/react";
import { devtools } from "@/lib/devtools";

export function Analytics({ children }) {
  return (
    <ReoptProvider config={{ writeKey, baseUrl: "/ingest", fetch: devtools.fetch, observe: devtools.observe }}>
      {children}
      <ReoptDevtools devtools={devtools} />
    </ReoptProvider>
  );
}

fetch records the wire batch without intercepting or patching globals and reduces signed-session request/response data to a boolean. Sensitive headers, common personal fields, URLs, responses, and identity facts are redacted before they enter the store. observe adds enqueue-time lifecycle, identity, consent, tracking, and sanitized configuration facts, so an event appears immediately and advances from queued through sending to accepted, failed, or dropped. The status bar shows anonymous or signed in independently from session pending, session active, or no session, without exposing either identifier. The same pair works next to init() without a provider.

The Events tab uses low-contrast phase backgrounds instead of card outlines. Newly inserted rows reveal from the top with a short motion, while prefers-reduced-motion disables that animation.

Options

createDevtools({ enabled, maxBatches, maxEvents, maxTimeline, captureRaw, fetch })

  • enabled — default process.env.NODE_ENV !== "production".
  • maxBatches — batches kept in memory, default 40.
  • maxEvents — event lifecycle rows kept in memory, default 250.
  • maxTimeline — identity, consent, and tracking rows kept in memory, default 100.
  • captureRaw — retain exact diagnostic values, default false. Use only on a trusted local page.
  • fetch — the transport to delegate to, default the page's fetch.

<ReoptDevtools devtools panels title bottomOffset console expose />

  • panels — extra tabs: [{ id, label, render }]. The reopt-data example app uses one for its SDK option switches.
  • bottomOffset — pixels to reserve below the tool for a host-owned footer.
  • console{ origin, projectId }; adds project and accepted-event links through the console's stable /open/projects/... resolver.
  • expose — install window.__reoptDevtools on mount (default true) so an end-to-end test can read the store:
const events = await page.evaluate(() => window.__reoptDevtools?.state().batches.flatMap((batch) => batch.events));

Reading the store yourself

import { useDevtoolsState } from "@reopt-ai/data-sdk-devtool/react";

const { batches, totals, identity } = useDevtoolsState(devtools);

The recorder redacts credentials and common personal fields before values enter memory, so the UI and window.__reoptDevtools are sanitized by default. Property names the recorder does not recognize can still carry sensitive application data; keep diagnostics scoped to development, staging, or an intentionally sanitized demo. captureRaw: true is an explicit local-only escape hatch.