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

ui-boundary-helper

v0.1.3

Published

A Next.js development tool that visualizes Server Components, Client Components, Suspense, cache, and Server Actions with interactive UI boundaries.

Readme

ui-boundary-helper

A Next.js App Router development tool that automatically annotates Server Components, Client Components, Suspense boundaries, cache directives, and Server Actions with interactive visual overlays.

See information.md for the meaning of popup fields, render-time measurements, directive labels, and toolbar controls.

See the changelog for changes in upcoming and previous releases.

The boundary toolbar includes a searchable navigator for detected components. Select a boundary to scroll to it and open its popup. Popup render history shows its total observed render count, recent average, and up to ten latest timings.

Install

Use the package manager already used by your project:

# npm
npm install ui-boundary-helper

# pnpm
pnpm add ui-boundary-helper

# Yarn
yarn add ui-boundary-helper

# Bun
bun add ui-boundary-helper

Troubleshooting npm install

If npm reports Cannot read properties of null (reading 'matches'), it may have encountered dependency links left by another package manager or a local linked package. This error alone does not indicate a Next.js compatibility problem. See the npm issue for this error.

If your project uses pnpm, Yarn, or Bun, use its matching install command above. For an npm project, try rebuilding the installed dependencies from the project root while keeping package-lock.json:

# macOS / Linux
rm -rf node_modules
npm install
npm install ui-boundary-helper

On Windows PowerShell:

Remove-Item -Recurse -Force node_modules
npm install
npm install ui-boundary-helper

Wrap the app

Enable automatic annotations in next.config.ts with the package's Next.js integration. It installs a source transform for local .tsx and .jsx files under both Turbopack and webpack:

import type { NextConfig } from "next";
import { withBoundaryDebug } from "ui-boundary-helper/next";

const nextConfig: NextConfig = {};

export default withBoundaryDebug(nextConfig);

Then add BoundaryProvider once in the root app/layout.tsx as the first direct child of <body>, wrapping your other providers and app content. The layout remains a Server Component; the provider receives children as a slot.

import { BoundaryProvider } from "ui-boundary-helper";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <BoundaryProvider debug={process.env.NODE_ENV === "development"}>
          {children}
        </BoundaryProvider>
      </body>
    </html>
  );
}

The transform reads local component files and directives as Next.js compiles them, then injects annotations automatically. Hot reload recompiles changed files and refreshes their annotations. Set debug to true or false in the layout to turn annotations on or off. It defaults to enabled in development and disabled in production. The provider adds no layout element, and annotations are drawn in a pointer-transparent overlay. DebugBoundary remains available for a manual override when needed:

import { DebugBoundary } from "ui-boundary-helper";

<DebugBoundary kind="client" name="HeroBanner.tsx">
  <HeroBanner />
</DebugBoundary>

Automatic labels use boundary type | component-file.tsx, such as Client Component | client-counter.tsx or Server Component | page.tsx. A Server Action is labeled Server Action. If you manually provide detail, it appears as a third field. Client annotations are blue, server annotations are red, cache annotations are green, and Suspense annotations are amber. Nested components receive separate outlines, so a server component containing a client component with a cached server child appears as nested layers. Labels sit above their outlines with visible spacing; the dotted borders and labels overlay the page without changing its layout.

While a boundary's popup is open, its background tint becomes darker to make the selected region stand out. Pinning the popup keeps that highlight active; closing it restores the normal tint. This follows the toolbar's global and per-kind background-color settings.

Use the minimize icon next to the pin icon to collapse popups to just the component name and controls. The minimize and transparency settings apply to every open popup; each popup keeps its own pin state. Click the expand icon to restore all fields. Minimizing works with pinned popups and keeps the boundary highlight active. Boundary visibility, background tint, per-kind visibility and tint, popup minimize, and popup transparency settings are saved in local storage and restored after a page refresh.

Choose Reset UI settings in the boundary toolbar to restore annotation visibility, colors, type filters, popup display, and toolbar appearance to their defaults.

For a region that represents multiple concepts, pass several kinds; their labels and outlines stack above and around the same region:

<DebugBoundary kinds={["cache", "server"]} name="CachedProductData">
  <ProductData />
</DebugBoundary>

DebugBoundary can receive Server Component output through children. For async server UI, SuspenseBoundary pairs a fallback with the resolved slot:

import { SuspenseBoundary } from "ui-boundary-helper";

<SuspenseBoundary name="ProductReviews" fallback={<ReviewsSkeleton />}>
  <ProductReviews />
</SuspenseBoundary>

The Next integration reads directives during compilation, not by inspecting runtime component objects. It adds a boundary around each detected local component, including the default page export, named component functions, components passed to wrappers such as memo, and React class render methods. A file with 'use client' is labeled as a Client Component; files without it are labeled as Server Components by default. Function-level 'use cache' directives receive cache and server annotations on that component. <Suspense> boundaries receive a persistent Suspense annotation, with the wrapped component name available on hover; forms using Server Actions receive annotations as well. A Server Action marked with 'use server' is a function, not a Server Component. The server-only and client-only package markers are also supported, but are not directives.

Render-time measurements

Each popup includes a timing value. Component timings measure the component function's execution up to its JSX return; async Server Components include work they await. They do not measure the full React subtree render, network transfer, or browser paint. A cached component reports its cache-generation timing, which can be reused on cache hits rather than measuring the cache lookup. Suspense reports the client-observed fallback wait when the fallback is observed, and Server Actions report the browser-observed submit-to-completion round trip rather than server-only execution time.

How cached component inputs work

Next.js uses the cached function or component and its serializable inputs to determine which result can be reused. Pass every value that can change the result into the cached component. A different input combination gets its own cache entry; a later render with the same inputs can reuse that entry while it is valid.

For example, a product variant can be cached by product ID and color:

type CachedBagProps = {
  productId: string;
  color: "green" | "blue";
};

async function CachedBag({ productId, color }: CachedBagProps) {
  "use cache";

  const bag = await getBagVariant(productId, color);

  return (
    <article>
      <img src={bag.imageUrl} alt={`${color} ${bag.name}`} />
      <h2>{bag.name}</h2>
      <p>Color: {color}</p>
      <p>{bag.price}</p>
    </article>
  );
}

("bag-123", "green") and ("bag-123", "blue") are separate entries. Another request for ("bag-123", "green") can reuse the green result. Include every result-changing input, such as size or locale, too. If almost every input combination is unique, caching may have few hits. A cached component's rendered markup and image URL may be reused; the image file itself is handled by the browser or image CDN cache separately. Set an appropriate cache lifetime or invalidate entries when product data changes. See Next.js' use cache documentation for cache keys, serialization, and invalidation.

The React wrapper uses React and React DOM. The optional Next integration uses TypeScript to transform app source files during builds.

Local example

This repository includes a deliberately small Next.js app under examples/next-app to try automatic annotations, the client island, cached server output, Server Actions, and Suspense boundaries.

pnpm install
pnpm --filter ui-boundary-helper build
pnpm --filter next-app-example dev

From the repository root, npm run dev starts the same example app.

Package development

pnpm build
npm pack
npm publish