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

@versini/ui-debug-overlay

v2.2.1

Published

[![npm version](https://img.shields.io/npm/v/@versini/ui-debug-overlay?style=flat-square)](https://www.npmjs.com/package/@versini/ui-debug-overlay) ![npm package minimized gzipped size](<https://img.shields.io/bundlejs/size/%40versini%2Fui-debug-overlay?s

Readme

@versini/ui-debug-overlay

npm version npm package minimized gzipped size

Lightweight always‑on React debug overlay for inspecting live state and manual snapshots (great on mobile / PWA / hybrid shells where devtools are awkward).

@versini/ui-debug-overlay lets you:

  • Automatically snapshot an appState object on referential changes
  • Push manual, labeled, color‑coded snapshots from anywhere (via a hook)
  • Target snapshots to specific overlay instances
  • Copy a merged chronological timeline (always includes manual snapshots)
  • Clear everything in a click
  • Position the panel with shorthands or explicit edges
  • Keep bundle weight minimal (inline styles only, no CSS frameworks)

Features

  • ⚡ Zero Config – Drop in and pass appState
  • 🔄 Auto State Capture – Retains a rolling window (FIFO) of snapshots
  • 📝 Manual Snapshots – Arbitrary data logging with labels & colors
  • 🎯 Targetable – Route manual events to named overlays
  • 🪄 Cycle‑Safe JSON – Deterministic, circular reference tolerant stringify
  • 📋 One‑Click Copy – Chronological timeline, numbering stable regardless of UI order
  • 🧹 Clear Control – Reset buffer instantly
  • 📐 Flexible Position – Shorthands or { top/right/bottom/left }
  • 🔍 Order Toggle – Show newest first while numbering still reflects true time
  • 🪶 Lightweight – Pure inline styling, TypeScript types

Installation

npm install @versini/ui-debug-overlay

Peer deps: react, react-dom.

Quick Start

import { DebugOverlay } from "@versini/ui-debug-overlay";

export function App() {
  const appState = { user: { id: 1, name: "Ada" }, online: true };
  return (
    <>
      <YourRealApp />
      <DebugOverlay appState={appState} />
    </>
  );
}

Manual Snapshots

Use the hook to push ad‑hoc snapshots (successful responses, errors, timings, etc.).

import { useDebugOverlay, LOG_GREEN, LOG_RED } from "@versini/ui-debug-overlay";

function SomeLogic() {
  const debug = useDebugOverlay();

  async function run() {
    debug("start", { ts: Date.now() });
    try {
      const data = await fetch("/api/data").then((r) => r.json());
      debug("success", data, LOG_GREEN);
    } catch (e) {
      debug("error", { message: (e as Error).message }, LOG_RED);
    }
  }

  return <button onClick={run}>Run</button>;
}

Multiple / Targeted Overlays

const debug = useDebugOverlay();

debug("metrics", { fps: 60 }, { targetOverlays: ["perf"] });

debug("state-change", someStateSlice); // broadcast to all overlays

return (
  <>
    <DebugOverlay overlayId="perf" position="left" title="Performance" />
    <DebugOverlay
      overlayId="main"
      position="right"
      title="Main State"
      appState={rootState}
    />
  </>
);

Rules:

  • Omit targetOverlays (or empty array) ⇒ broadcast
  • Non‑empty array ⇒ deliver only to overlays whose overlayId matches
  • Buffered (pre‑mount) manual snapshots still respect targeting when overlays mount

Positioning

<DebugOverlay position="bottom-right" />
<DebugOverlay position="left" />                {/* alias of top-left */}
<DebugOverlay position={{ bottom: "8px", left: "8px" }} />

Supported shorthands: left, right, top, bottom, top-left, top-right, bottom-left, bottom-right.

Copy Behavior

Pressing "Copy" produces a plain text timeline. Chronological numbering always starts at #1 (oldest), even if UI order shows newest first. Manual snapshots are always included.

Collapsing

<DebugOverlay initialCollapsed />

Props

| Prop | Type | Default | Description | | ---------------------------- | -------------------------- | ------------ | -------------------------------------------------------------------- | ---------------------------------------------------- | | appState | unknown | – | Value to snapshot on reference change. Omit for manual‑only overlay. | | title | string | "AppState" | Panel header. | | initialCollapsed | boolean | false | Start minimized. | | overlayId | string | "default" | Name used for targeted manual snapshots. | | position | shorthand | partial edges | – | Placement via shorthand or { top/right/bottom/left }. | | maxBodyHeight | number | string | 320 | Scroll region max height. | | indent | number | 2 | JSON indent spaces. | | maxSnapshots | number | 50 | Retained automatic state snapshot cap (FIFO). | | maxVisibleSnapshots | number | 10 | Visible snapshot limit; remainder summarized. | | snapshotOrder | "asc" | "desc" | "desc" | Visual ordering only. Numbering stays chronological. | | appendSnapshotCountInTitle | boolean | false | Append live count to title. |

Hook: useDebugOverlay()

const debug = useDebugOverlay();

debug(
  label: string,
  data: unknown,
  options?: LogColor | { color?: LogColor; targetOverlays?: string[] }
);

Color constants: LOG_YELLOW, LOG_GREEN, LOG_BLUE, LOG_MAGENTA, LOG_RED (yellow is default fallback).

Tips

  • Keep maxVisibleSnapshots small (1–3) on narrow/mobile viewports
  • Derive / shape very large objects before passing to reduce noise & stringify cost
  • Multiple overlays can focus on separate domains (state vs. performance vs. network)
  • Use colors to visually cluster snapshot categories (success, error, timing)

License

MIT © Arno Versini