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

uipin

v0.1.0

Published

Pin UI comments on your running React app and hand them to a coding agent, with the source file and line attached

Readme

uipin

Pin comments on your running React app, collect them, and hand the batch to a coding agent — with the source file and line already attached.

You are looking at a screen and something is off. Normally you describe it and the agent goes hunting through the codebase. uipin lets you point at it instead:

--- [1/2] "카드 간격이 들쭉날쭉해 보임" ---
선택: 영역 드래그 · 요소 3개 · 뷰포트 375×812

  1) <article class="rounded-xl bg-w...">
     AnniversaryCard  @ src/components/Card.tsx:12:5
     key "결혼기념일"
     class rounded-xl bg-white shadow-sm p-4
     padding: 16px · border-radius: 12px
     327×84 · 부모 327×280

  2) <article class="rounded-xl bg-w...">
     AnniversaryCard  @ src/components/Card.tsx:12:5
     key "첫 만남"
     class rounded-xl bg-white shadow-sm p-[14px]
     padding: 14px · border-radius: 12px          ← the odd one out
     327×80 · 부모 327×280

Three cards, same component, same line. The React key says which is which, and p-[14px] next to p-4 makes the bug visible without anyone diagnosing it.

What it reports

  • Where it lives — file, line and column of the JSX that rendered it, plus the components that own it
  • What is actually on screen — the class list next to the computed values, so a p-3 that renders 14px stands out
  • Viewport size — a layout that only breaks at 375px is unreproducible without it
  • Text overflow — measured with a Range, because scrollWidth reports nothing once an ancestor sets overflow: hidden

It reports observations and no diagnosis. Deciding what is wrong is the agent's job, and it can read the design tokens out of your codebase itself.

Install

npm i -D uipin

1. Mount the picker

// app/layout.tsx
import { UipinMount } from "./uipin-mount";

// ...
{process.env.NODE_ENV === "development" && <UipinMount />}
// app/uipin-mount.tsx
"use client";

import { useEffect } from "react";
import { startUipin } from "uipin";

export function UipinMount() {
  useEffect(() => {
    startUipin();
  }, []);
  return null;
}

2. Add the queue route

// app/api/uipin/route.ts
export { GET, PUT, DELETE } from "uipin/next";

The browser mirrors its queue through this route to node_modules/.cache/uipin/queue.json, where the agent reads it.

3. ⚠️ Exclude the route from auth middleware

If your app has middleware that guards /api, add an exemption. The picker posts without a session, and middleware that answers with a login page returns 200 — so the write silently does nothing.

// middleware.ts
export const config = {
  matcher: ["/((?!_next/static|api/uipin|...).*)"],
};

uipin turns the sync dot red and logs when this happens, but it is the single most common setup mistake.

4. Register the MCP server

npm i -D uipin-mcp
// .mcp.json
{
  "mcpServers": {
    "uipin": {
      "command": "node",
      "args": ["./node_modules/uipin-mcp/src/server.ts", "."]
    }
  }
}

Requires Node 22.6+, which strips TypeScript types natively.

Use

| | | |---|---| | ⌥G | enter and leave pick mode | | hover | highlight the element under the cursor | | click | pin it | | drag | pin several elements as one comment | | ↑ ↓ | widen or narrow the selection — outward through ancestors, or between nesting levels after a drag | | Esc | cancel |

The badge counts what is pinned. Click the count to review the list and delete individual items. The queue survives reloads and navigation, so a review can span several pages.

Then, in your agent:

쌓아둔 거 처리해줘

It calls get_queue, works through the batch, and calls clear_queue when done.

Tools

| Tool | | |---|---| | get_queue | Read the pinned comments | | clear_queue | Empty the queue once the batch is handled |

Requirements

  • React 19 in a development build — the source locations come from _debugStack, which production builds do not carry
  • Next.js — the queue route ships for Next today. The browser half is framework-agnostic; other adapters are not written yet.
  • Chromium — Firefox and Safari lack the V8 CallSite API, so source locations degrade to string-parsed stack traces
  • Server Components have no client fiber, so elements rendered purely on the server cannot be traced back

How it works

The hard part — turning a DOM node into a source location — is react-grab's. React's dev build attaches an Error to every jsxDEV() call, and react-grab reads that stack and resolves it through the source map. uipin pins it at 0.1.50.

What uipin adds on top: path normalization, style condensing, overflow measurement, the queue, nesting levels, and the handoff to an agent.

react-grab is pre-1.0 and moves quickly, so uipin depends on an exact version rather than a range. Upgrading it is a deliberate release here.

Development

pnpm install
pnpm --filter uipin build
pnpm --filter uipin test
pnpm -C fixture dev        # test app on :3100, with three planted bugs

fixture/ is a small Next app whose bugs are documented in its README — the expected values double as the accuracy oracle.

License

MIT