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

universal-bridge

v0.5.0

Published

A protocol for exposing and controlling local processes across frameworks and runtimes.

Downloads

447

Readme

Universal Bridge banner

Universal Bridge: A Protocol for Local Services

Protocol Frameworks + Runtimes MIT License

Universal Bridge is a framework- and runtime-agnostic protocol for mounting a same-origin control plane for local companion processes.

Frameworks and runtimes expose different dev-server integration points—plugins, rewrites, middleware, and server APIs. Without a shared layer, each tool needs a separate integration for every host.

Universal Bridge mounts that shared layer at /__universal/*, providing HTTP health/state/control routes, WebSocket events, an optional runtime WebSocket gateway, and API proxying. Framework-specific adapters translate it for each host environment.

Who is this for?

Use Universal Bridge when you're building a developer tool—such as an overlay, panel, CLI companion, or local service—that needs to work across frameworks and server runtimes.

If you're using a tool that already includes Universal Bridge integration, configure that tool instead; you usually do not need to install Universal Bridge directly.

Universal Bridge reference dashboard

Table of Contents

Installation

npm i universal-bridge
pnpm add universal-bridge
yarn add universal-bridge
bun add universal-bridge

What it provides

  • same-origin bridge endpoints under /__universal/*
  • runtime lifecycle control (start/restart require command; stop is idempotent)
  • runtime status and capability reporting for UIs/automation
  • websocket event stream with protocol versioning
  • optional same-origin runtime WebSocket gateway
  • /api/* passthrough proxy from host origin to runtime origin
  • framework/server/build-tool adapter surfaces plus a preset API for tool packages

Non-goals:

  • no first-party UI or hosted service
  • no requirement that end users import UniversalBridge directly when a tool already wraps it

Use cases

  • devtool overlays/sidebars/panels that should run across frameworks
  • local CLIs/scripts that need runtime status and control via the same bridge
  • internal developer platforms that expose same-origin local control APIs

Quick start (Vite)

// vite.config.ts
import { createUniversalVitePlugin } from "universal-bridge/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    createUniversalVitePlugin({
      command: "node",
      args: ["./scripts/dev-runtime.js"],
    }),
  ],
});

Core concepts

  • Bridge path prefix: defaults to /__universal.
  • Runtime helper: optional process manager for your tool runtime command.
  • Protocol version: current bridge protocol is 2 (universal.v2+json for negotiated event sockets).
  • Preset API: recommended integration API for tool authors so users configure one entry point (mytool().vite(), mytool().next(...), etc.).

Integration and runtime surfaces

| Surface | Import path | | ------------------------------------------------------------------------------------------ | ------------------------------ | | Vite-based dev servers (React, Vue, Solid, SvelteKit, Remix, TanStack Start, Vinext, etc.) | universal-bridge/vite | | Next.js | universal-bridge/next | | Nuxt | universal-bridge/nuxt | | Astro | universal-bridge/astro | | Angular CLI proxy flow | universal-bridge/angular/cli | | Bun.serve | universal-bridge/bun | | Node middleware + HTTP server | universal-bridge/node | | Express middleware | universal-bridge/express | | Fastify | universal-bridge/fastify | | Hono on Node server | universal-bridge/hono | | webpack-dev-server | universal-bridge/webpack | | Rsbuild dev server | universal-bridge/rsbuild | | Rspack dev server | universal-bridge/rspack | | Docker Compose runtime helper for adapters that manage a process | universal-bridge/docker |

Public API reference

Primary exports

| API | Import | | ------------------------------------------- | --------------------------------- | | createUniversalPreset | universal-bridge/preset | | createUniversalClient | universal-bridge/client | | createBridgeRuntimeStore | universal-bridge/client | | createClientRuntimeContext | universal-bridge/client-runtime | | createDockerComposeRuntime | universal-bridge/docker | | attachUniversalToExpress | universal-bridge/express | | startStandaloneUniversalBridgeServer | universal-bridge | | createUniversalBridge / UniversalBridge | universal-bridge |

The root package resolves to a browser-only client surface in browser builds. Import server APIs from universal-bridge in server code, and import browser APIs explicitly from universal-bridge/client when that makes the boundary clearer.

Adapter naming conventions

  • createUniversal*: build a plugin/module/integration instance.
  • withUniversal*: wrap and return config.
  • attachUniversalTo*: attach to an existing server.
  • startUniversal*: start helper/standalone utilities.

For expanded API coverage (including lifecycle helpers, runtime-context utilities, and adapter-specific helper exports), see INTEGRATION_GUIDE.md.

Configuration

Most adapter APIs accept shared bridge/runtime options.

| Option | Type | Default | Notes | | -------------------------- | ------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------ | | bridgePathPrefix | string | "/__universal" | Normalized to stay rooted under /__universal. | | autoStart | boolean | true | Auto-start runtime on state, proxy, events, and runtime WebSocket gateway paths. | | command | string | none | Required for managed runtime start/restart. | | args | string[] | [] | Runtime command args. | | cwd | string | process.cwd() | Runtime working directory. | | env | Record<string, string \| undefined> | none | Extra runtime environment variables. | | host | string | "127.0.0.1" | Runtime host binding. | | healthPath | string | "/api/version" | Runtime health probe endpoint. | | startTimeoutMs | number | 15000 | Runtime startup timeout. | | runtimePortEnvVar | string | "UNIVERSAL_RUNTIME_PORT" | Env var populated with selected runtime port. | | fallbackCommand | string | "universal dev" | Returned in some runtime-control error payloads. | | eventHeartbeatIntervalMs | number | 30000 | WS heartbeat for stale client cleanup. | | runtimeWebSocketGateway | { path: string } | none | Opt-in gateway at /runtime/ws to one managed runtime WebSocket path. | | instance | { id: string; label?: string } | none | Optional instance metadata in bridge state/health. | | additionalRewriteSources | string[] | [] | Extra path prefixes proxied directly to the runtime by adapters that support direct passthrough. |

Preset-specific options (createUniversalPreset)

  • identity (required): { packageName: string; variant?: string }
  • composition: "registry" | "local"
  • instanceId: stable suffix for multiple preset instances
  • unsafeOverrides: advanced adapter identity overrides
  • client.entries: self-initializing browser modules loaded in development by the Vite, Next.js, Nuxt, and Astro preset adapters

Protocol summary

With prefix /__universal (or /__universal/<namespaceId> for presets):

  • GET /health
  • GET /state
  • GET /runtime/status
  • POST /runtime/start
  • POST /runtime/restart
  • POST /runtime/stop
  • WS /events
  • WS /runtime/ws (when runtimeWebSocketGateway is configured)
  • ANY /api/* proxied to runtime /api/*

Behavior highlights:

  • Route matching is query-safe.
  • GET /state, WS /events, WS /runtime/ws, and proxy requests may auto-start runtime when autoStart is enabled.
  • POST /runtime/stop is idempotent and disables auto-start, including gateway-triggered auto-start, until start/restart.
  • WS /events carries bridge protocol events only.
  • WS /runtime/ws forwards one configured runtime WebSocket path without parsing app messages; runtime close/error affects only the paired gateway socket.
  • Bridge-generated errors use { success: false, message, error } envelope.
  • Proxied /api/* responses pass through status/headers/body (including non-2xx).

For normative protocol details, see PROTOCOL.md.

For adapter-specific snippets (Next keying, Bun/Node/Express/Fastify/Hono servers, Docker Compose runtime helpers, webpack/Rsbuild/Rspack, Astro/Nuxt, Angular CLI, and standalone bridge usage), see INTEGRATION_GUIDE.md.

Usage examples

Preset export for your tool package

import { createUniversalPreset } from "universal-bridge/preset";

export function myTool() {
  return createUniversalPreset({
    identity: { packageName: "mytool" },
    client: {
      entries: [{ module: "mytool/overlay" }],
    },
    command: "mytool",
    args: ["dev"],
    fallbackCommand: "mytool dev",
  });
}

Entries load once per page in development. Each can read its derived namespace and bridge prefix with resolveClientRuntimeContext("mytool/overlay"), then mount its own UI. See the integration guide for a complete example and multiple-instance constraints.

Next.js

// next.config.ts
import { myTool } from "mytool";

export default myTool().next({ reactStrictMode: true });

Vite (including Vinext)

// vite.config.ts
import { myTool } from "mytool";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [myTool().vite()],
});

Client SDK

import { createUniversalClient } from "universal-bridge/client";

const client = createUniversalClient({ namespaceId: "mytool" });
const state = await client.getState();
const runtimeSocket = new WebSocket(
  client.getRuntimeWebSocketUrl({ query: { session: "local" } }),
  ["mytool.v1"],
);

const unsubscribe = client.subscribeEvents((event) => {
  if (event.type === "bridge-state") {
    console.log(event.state.runtime.phase, event.state.revision);
  } else {
    console.error(event.error);
  }
});

unsubscribe();

Architecture overview

High-level internals:

  • src/bridge/*: HTTP/WS routing, runtime control routes, proxying, event fanout.
  • src/runtime/runtime-helper.ts: command lifecycle and health probing.
  • src/adapters/*: framework/server/build-tool integration points.
  • src/client/*: typed browser/Node client helpers.
  • src/preset.ts + src/preset-registry.ts: preset composition and registry behavior.

For implementation details, see ARCHITECTURE.md.

Design caveats

  • UniversalBridge does not ship a first-party UI.
  • Runtime start/restart are unavailable when command is not configured.
  • The runtime WebSocket gateway is opt-in, proxies only its configured runtime path, and forwards text/binary frames opaquely.
  • /events is bridge-only; runtime/app WebSocket traffic belongs on /runtime/ws.
  • The bridge does not reconnect runtime WebSockets, replay application traffic, or interpret application messages.
  • bridgePathPrefix is normalized under /__universal.
  • Package is ESM-only ("type": "module").

Compatibility

  • Runtime targets: Node.js and Bun.
  • Package format: ESM-only ("type": "module").

Additional docs

Docs checks:

bun run docs:lint
bun run docs:check