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

@zap-proto/web

v1.0.0

Published

Browser frontend RPC over ZAP — a drop-in tRPC replacement for Next.js / Remix / SvelteKit. Native ZAP envelopes over WebSocket binary frames, plus an optional JSON-over-HTTP face (httpServe) for the OpenAPI 3.1 surface emitted by zapgen. Layered on @zap-

Downloads

776

Readme

@zap-proto/web

Browser-frontend RPC over ZAP — a drop-in tRPC replacement for Next.js / Remix / SvelteKit. Native ZAP envelopes over WebSocket binary frames, layered cleanly on @zap-proto/zap (the ZAP wire runtime). v0.1.0 — pre-1.0 by policy; no version tags until the full chain works end-to-end.

Note on naming. The foundation runtime is @zap-proto/zap (the canonical TypeScript ZAP runtime, repo zap-proto/ts). This package — the WebSocket frontend layer — is @zap-proto/web, repo zap-proto/web. It is not Cap'n Proto; ZAP is a zero-copy, zero-dependency binary format byte-compatible with the Go runtime github.com/zap-proto/go and github.com/luxfi/zap.

What @zap-proto/web IS

  • A drop-in replacement for tRPC across Hanzo's TS apps (esign, console, platform), using native ZAP RPC over WebSocket instead of JSON-over-HTTP.
  • An isomorphic transport — the same WsTransport works in Node (post HTTP-upgrade, over the ws package) and in the browser (native WebSocket).
  • A Node serve(httpServer, opts) harness that attaches to an existing http.Server, so Next.js (app.getRequestHandler()) or a Remix Node server share one port — integration is one line.
  • A browser connect(url, opts) that opens the WS, waits for open, and returns the bootstrap call surface typed by your generated bindings.
  • A mintCap boundary hook at the WS upgrade so apps plug their own bearer→context minting logic.

What @zap-proto/web is NOT

  • Not a Zod/procedure DSL like tRPC. Service shape comes from .zap schemas (structs + method ordinals), codegen'd via zapgen --target=ts from zap-proto/ts.
  • Not a JSON wrapper. Wire format is ZAP envelopes over WS binary messages. Text frames are a protocol violation and close the socket with WS code 1003.
  • Not Cap'n Proto. ZAP is its own zero-copy format. The bootstrap is the connection's call surface (bootstrap.call(method, { payload })), not a Cap'n Proto capability object.
  • Not a bearer-JWT framework. mintCap is a slot — apps provide a fn (upgradeReq) => Promise<Ctx | null>. v0 ships the slot; the canonical ML-DSA-65 signed Capability mint (per zap-spec/capabilities.zap — the 3408-byte signature footer, BLAKE3 identity, attenuable/revocable authority) lands in a later version. Until then, whatever non-null value mintCap returns becomes the per-connection ctx.

Install

pnpm i @zap-proto/web @zap-proto/zap

@zap-proto/zap is not yet published to npm. The dependencies entry already ships plain semver (^0.1.0); until it lands on npm, local tests resolve the specifier to the sibling source tree (../ts, the zap-proto/ts repo) via the vitest.config.ts alias and the tsconfig.json path. No change needed once @zap-proto/zap ships — just drop the alias.

Quick start — Next.js (≈30 lines)

// server.ts
import http from "node:http";
import next from "next";
import { serve } from "@zap-proto/web/server";
import { newGreeting, HelloArgs } from "./gen/hello_zap.js"; // zapgen --target=ts

const app = next({ dev: process.env.NODE_ENV !== "production" });
const handle = app.getRequestHandler();

await app.prepare();
const server = http.createServer((req, res) => handle(req, res));

serve(server, {
  path: "/zap",
  // mintCap SLOT: turn a bearer into your app's ctx. Return null → HTTP 401.
  mintCap: async (req) => {
    const auth = req.headers.authorization;
    return auth ? { org: await orgFromBearer(auth) } : null;
  },
  // rootCap(ctx): dispatch every decoded ZAP Call for this connection.
  rootCap: (ctx) => (call) => {
    const args = HelloArgs.wrap(call.payload);
    return {
      status: 200,
      promiseID: call.promiseID,
      body: newGreeting({ text: `hi ${args.name} @ ${ctx.org}` }),
    };
  },
});

server.listen(3000);
// client.ts (browser)
import { connect } from "@zap-proto/web/client";
import { newHelloArgs, Greeting } from "./gen/hello_zap.js";

const { bootstrap, close } = await connect("wss://app.hanzo.ai/zap", {
  bearer: sessionToken, // forwarded as Authorization on the upgrade (Node ws)
});

const resp = await bootstrap.call(/* method */ 0, {
  payload: newHelloArgs({ name: "ada" }),
});
console.log(Greeting.wrap(resp.body).text); // "hi ada @ acme"
close();

Browser bearer caveat. The browser's native WebSocket cannot set an Authorization header. In the browser, connect({ bearer }) falls back to a ?authorization=Bearer%20… query param the server can read; prefer a cookie sent automatically on the upgrade for production. The header path applies to a header-capable WebSocketImpl (the ws package, used in Node/SSR/tests).

Schema → code

Service shape is .zap schemas compiled with the ZAP compiler from zap-proto/ts:

zapgen --target=ts -single hello.zap   # → hello_zap.ts (views + builders)

Method ordinals (the interface method @n) are the integers you pass to bootstrap.call(method, …) and match in your rootCap dispatch.

Entry points

The root entry (@zap-proto/web) is browser-safe — it imports no Node built-ins and exposes only the client surface (connect, browserWsTransport, Conn, errors). The Node server (serve, nodeWsTransport, the MintCap auth slot) reaches node:module (createRequire) / node:http / node:net and lives behind @zap-proto/web/server, so it never enters a browser bundle.

// Browser — the client connection.
import { connect } from "@zap-proto/web/client";

// Node — attach the RPC endpoint to an http.Server.
import { serve } from "@zap-proto/web/server";

API

| Export | Entry | Purpose | | --- | --- | --- | | connect(url, opts?) | @zap-proto/web/client (or root) | Open a ZAP RPC WebSocket; returns { bootstrap, close }. | | browserWsTransport(ws) | @zap-proto/web/transport (or root) | Wrap a native WebSocket as a WsTransport. | | Conn, WebRpcError | @zap-proto/web (root, browser-safe) | Duplex RPC connection; transport-level RPC failure. | | serve(httpServer, opts) | @zap-proto/web/server | Node only. Attach a ZAP RPC endpoint to a Node http.Server. | | nodeWsTransport(ws) | @zap-proto/web/server (or /transport) | Node only. Wrap a ws WebSocket as a WsTransport. | | MintCap<Ctx> | @zap-proto/web/server (or /auth) | Node only. The bearer→ctx slot. |

License

MIT © Lux Industries Inc.