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

@nice-code/devtools-relay

v0.58.0

Published

Readme

@nice-code/devtools-relay

Docs: nicecode.io — guides, integrations, and the full API surface. Working with an AI assistant? Point it at nicecode.io/llms.txt — the complete, current docs flattened into plain text.

A tiny, reusable WebSocket relay that lets the nice-* devtools span browser storage partitions — a private window, a different browser profile, a different browser, even a different device — which same-origin BroadcastChannel cannot cross (each partition is isolated by design, which is also why those environments connect as a distinct client).

App clients and the devtools window each dial the relay; it rooms them by an app name and fans every frame out to the room's other members. It is purely ephemeral — no history, no content logging.

Runs on Bun (Bun.serve) or Node (node:http + ws), picked at runtime by startDevtoolsRelayAuto.

Let Vite run it for you

Usually you should not run this by hand at all. Add @nice-code/devtools-vite to your Vite config and the relay starts on the first devtools click, with every local client discovering it — no port to configure, no second terminal:

import { niceDevtools } from "@nice-code/devtools-vite";
export default defineConfig({ plugins: [react(), niceDevtools()] });

Or run it yourself

bunx @nice-code/devtools-relay            # port 5199, binds 0.0.0.0
bunx @nice-code/devtools-relay --port 6000 --host 127.0.0.1

Environment fallbacks: DEVTOOLS_RELAY_PORT, DEVTOOLS_RELAY_HOST.

Then point your app's relay URL at it — relayUrl on the devtools config, or VITE_DEVTOOLS_RELAY_URL in the demos. An explicit URL bypasses discovery entirely. The devtools transport connects with ?key=<app-name> so unrelated apps on one relay never cross streams.

GET /health answers { "service": "nice-devtools-relay", "protocol": 1, "rooms": N }. The service marker is what lets a prober tell a relay apart from anything else that happens to hold the port — liveness is not identity.

Embed it

import { startDevtoolsRelayAuto } from "@nice-code/devtools-relay";

const relay = await startDevtoolsRelayAuto({ port: 5199 });
// …
relay.stop();

startDevtoolsRelay (Bun) and startDevtoolsRelayNode (Node) are exported directly when you know which host you want. Both reject with an EADDRINUSE error — recognisable via isAddressInUseError — when the port is taken, which a caller racing several dev servers onto one well-known port should treat as "someone else's relay won" rather than a failure. probeRelay(url) answers "relay" | "other" | "down".

Extend it

The room/fan-out logic lives in DevtoolsRelayHub, which is transport-agnostic (it forwards opaque frames and knows nothing about WebSockets or the devtools protocol). Wrap it in whatever carrier you need — the Bun server here, a Node ws server, or a Cloudflare Durable Object for remote hosting:

import { DevtoolsRelayHub } from "@nice-code/devtools-relay";

const hub = new DevtoolsRelayHub();
hub.join(roomKey, conn); // conn: { send(data: string): void }
hub.relay(conn, frame); // → every other member of conn's room
hub.leave(conn);

Security

It is an unauthenticated, ephemeral relay meant for local/dev use. The CLI binds 0.0.0.0 by default so other devices on your LAN can reach it — pass --host 127.0.0.1 to keep it same-machine only. (A relay started for you by the Vite plugin binds loopback by default instead, on the grounds that a server nobody consciously started should not be reachable from the network.) Do not expose it to the public internet or point it at production clients without adding auth and gating.