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

@justuswitmer/fiber-inspector

v0.1.1

Published

In-app overlay for exploring a running React app's Fiber tree.

Readme

React Fiber Inspector

An in-app overlay for exploring a running React app. Hover any rendered element to see the component behind it, its props, hook/class state, subscribed context, ancestors, and the tree of what it renders. Click to pin and walk the tree. The goal is to learn an unfamiliar codebase by exploring its live UI instead of reading files.

It reads React's internal Fiber tree directly off the DOM at runtime. No browser extension, no DevTools hook, no required build step. Works on React 17, 18, and 19.

Features

  • Panel — props, named hooks (useState (0) instead of hook 0, from dev-build _debugHookTypes), subscribed context, ancestors breadcrumb, rendered-structure tree. Sections collapse individually; click a section title.

  • Component map (⌗ map) — graph centered on the selected component: ancestor chain branching left, descendant tree branching right. Click any node to re-center. Export as Mermaid or JSON from the header.

  • App map (⌗ in the toolbar) — the same graph for the entire mounted tree, from the app root down, with zoom controls and Mermaid/JSON export. Click any node to select it in the panel. "Your components" mode keeps it readable; "all" mode shows everything.

  • All-source mode in the app map — the fiber tree only contains mounted components, so route-gated components (cart, checkout, etc.) are invisible until you navigate to them. The bundled scanner (scan-components.cjs) statically analyzes your src/ and produces a JSON graph of every component and what it renders. Pass it via <Inspector staticMap={map} /> and the app map gains a "mounted / all source" toggle: green = mounted now, gray = defined but not mounted; clicking a mounted node inspects it, clicking an unmounted one copies its file path. Regenerate on dev start with a prestart script:

    "prestart": "node node_modules/@justuswitmer/fiber-inspector/scan-components.cjs src --out src/fiberInspectorMap.json"
    import staticMap from "./fiberInspectorMap.json";
    <Inspector staticMap={staticMap} />;
  • Source (file:line) — copy the full path or open it in your editor (editorUrlTemplate prop; defaults to VS Code). See "Source locations" below.

  • Search — type a name in the panel to find every mounted component matching it; click to select and scroll to it.

  • Instance cycling — when several instances of the selected component are mounted, ‹ › steps through them.

  • Keyboard walking — while pinned: ↑ parent, ↓ first child, ←/→ siblings.

  • Render tracking (⚡) — flashes components on screen as they re-render, counts renders of the selection, and lists which props changed in its last re-render. Detection works by polling for fiber-pair swaps; no DevTools hook.

  • Live watch — while pinned, the panel re-reads the fiber every 400ms so values stay current.

  • Mount snapshot/diff (◎ / Δ) — snapshot what is mounted, interact with the app, then diff to see which components mounted/unmounted and count changes.

  • State editinguseState hooks and class state with primitive values get a ✎ button; commit a new value and watch the UI respond. Edits dispatch through React, so they are real state updates.

  • Owner row — "rendered by" shows the component whose JSX created the selection when it differs from the nearest ancestor (dev builds).

Source locations

The source section shows file:line for the selected component, with a "copy path" button (copies the full absolute path:line:column for pasting into an IDE) and an "open" link that launches your editor. The link defaults to VS Code; override it via the editorUrlTemplate prop, e.g. <Inspector editorUrlTemplate="cursor://file/{path}:{line}:{column}" />.

Where the location comes from: on React 17/18 dev builds it is read from the fiber's _debugSource. React 19 removed that field, so the Babel plugin now also records Component.__sourceLoc = "file:line:column" at build time, which the inspector reads as a fallback. Add the plugin (see its header comment for Vite/Babel setup) to get locations on React 19 — strict mode is not required.

Installation

This package is published as @justuswitmer/fiber-inspector on npm.

Install:

npm install @justuswitmer/fiber-inspector

Then import by name:

import { Inspector } from "@justuswitmer/fiber-inspector";

function App() {
  return (
    <>
      <YourApp />
      {process.env.NODE_ENV !== "production" && <Inspector />}
    </>
  );
}

react is a peer dependency (v17+) and is not bundled; it resolves from the consuming app. Render <Inspector /> once, near the app root, behind a dev check.

The optional Babel plugin is exposed at a subpath:

const tagAppComponents = require("@justuswitmer/fiber-inspector/babel-plugin");

Configuring which components are "yours"

React records no source file on a fiber, so there is no runtime way to tell app code from node_modules code. The inspector offers two strategies, configured by props rather than by editing source.

Name heuristic (default)

A component is treated as "yours" unless its name matches ignoreNames or ignorePatterns. Tune these to match the libraries the project uses:

<Inspector
  ignoreNames={["Grid", "Box", "Stack", "MyDesignSystemPrimitive"]}
  ignorePatterns={[/^Chakra/, /Provider$/]}
/>

Passing either prop replaces the corresponding default set. The defaults are exported if you want to extend rather than replace them:

import { Inspector, DEFAULT_IGNORE_NAMES } from "@justuswitmer/fiber-inspector";

<Inspector ignoreNames={[...DEFAULT_IGNORE_NAMES, "MyPrimitive"]} />;

Build marker (exact)

The optional Babel plugin tags every component defined in your source with Component.__appComponent = true. Bundlers do not run Babel over node_modules, so library components never get the flag. Wire the plugin into your build, then set strict:

<Inspector strict />

With strict, only tagged components count and no name guessing happens. See the plugin file header for the Vite config snippet. Note: Next.js uses SWC and does not run JS Babel plugins without opting out of SWC; on Next, prefer the name heuristic.

Props

| Prop | Type | Default | Purpose | | ---------------- | ------------------ | ------------------ | ------------------------------------------------------- | | strict | boolean | false | Only build-marked components count as app components. | | marker | string | "__appComponent" | Property name the Babel plugin sets on user components. | | ignoreNames | Iterable<string> | built-in set | Component names hidden in "your components" mode. | | ignorePatterns | RegExp[] | built-in list | Name patterns hidden in "your components" mode. | | defaultAppOnly | boolean | true | Whether the panel opens in "your components" mode. |

Using the building blocks

The lower-level functions are exported for building custom tooling on the same Fiber-access layer:

import {
  getFiberFromNode,
  createClassifier,
  inspect,
} from "@justuswitmer/fiber-inspector";

const fiber = getFiberFromNode(document.querySelector("#some-node")!);
const classifier = createClassifier({ strict: true });
const data = fiber && inspect(fiber, classifier, { appOnly: true, snap: true });

How it works

Every DOM node React renders carries a hidden property __reactFiber$<random> pointing to its Fiber node. From a fiber you can walk the live render tree: type identifies the component (unwrap memo / forwardRef via $$typeof), memoizedProps holds current props, memoizedState holds class state or a linked list of hook records, dependencies.firstContext holds subscribed contexts, and return / child / sibling link the tree.

Hover snapping: in "your components" mode the inspector walks up via fiber.return until it reaches an app component, so hovering a <div> inside MyComponent → Grid → div → button snaps to MyComponent. In "all" mode it snaps to the nearest component fiber.

Known limitations

  • Hook names. React does not expose hook variable names at runtime, only the linked list of hook records. The panel shows hook 0, hook 1, etc. in call order. Mapping these back to const [cartCount] = useState(2) requires source parsing, which this does not do.
  • Source location. React 18 exposed fiber._debugSource with file and line; React 19 removed it (facebook/react#28265). The panel reads it when present and shows "not available at runtime" otherwise. Restoring editor-jump on React 19 needs a build-time JSX-source plugin plus a dev-server endpoint.
  • Large trees. The structure walk caps at maxNodes = 160 and maxDepth = 8 (in inspect.ts). Raise them if a real app hits the caps.

Prior art

  • react-dev-inspector — in-app overlay with editor jump.
  • bippy — safe Fiber access across React 17–19 by registering as a fake DevTools hook. If you want source-aware features without owning the internals-access code, leaning on bippy for the access layer is the better path than maintaining the direct-access utilities here.