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

@kairotic/relay

v0.3.0

Published

A GUN relay for Kairotic: passes works and rooms between browsers and keeps a copy, so a community can collaborate through its own server; an OSC bridge for the pages, and rooms where they open direct channels and share a clock

Readme

Kairotic relay

Versión en español

A GUN relay for Kairotic Pages: it passes the graph between browsers (rooms, presence, saved works) and keeps a copy on disk. Each community can run its own and collaborate through it: the rooms of one relay are not seen through another. See docs/pages.md.

npx @kairotic/relay                          # ws://localhost:8765/gun, data in ./radata
npx @kairotic/relay --port 9000 --data /srv/kairotic
PORT=9000 RADATA=/srv/kairotic npx @kairotic/relay

From this folder instead: npm install && npm start. Node 18 or later, and git (GUN comes from its repository, at the commit the page uses).

Then, in Kairotic: Sessions → Relay, write wss://<your host>/gun and Use. The page reloads syncing through it, and while it is not the site's relay the address and the room links carry it (?peer=…), so whoever you send them to lands on the same relay. For a whole site, put it in site/config.js.

Where to run it

| | | |---|---| | A VPS or a server of your own | npx @kairotic/relay --data /srv/kairotic behind a reverse proxy with TLS (Caddy, nginx) | | Docker | docker build -t kairotic-relay relay/ · docker run -p 8765:8765 -v kairotic-radata:/data kairotic-relay | | Fly.io | from relay/: fly launch --copy-config, fly volumes create radata --size 1, fly deploy (fly.toml) | | Render | the button uses render.yaml; free instances sleep and lose their disk | | Railway | a new service from this repository with root directory relay (it finds the Dockerfile); add a volume at /data | | Your own computer | npx @kairotic/relay and a tunnel with TLS (cloudflared, ngrok) for others to reach it |

Rooms and a shared clock

On ws://<host>/signal (on unless --no-signal) the pages of a room find each other: through it they open WebRTC data channels to each other for the stream of gestures (unordered, without retransmits — a gesture that arrives late is worth nothing), and while a channel is not open the relay passes the stream itself. The same socket answers {ping: t0} with the relay's time, so every page estimates its offset to it and they all read the same shared clock; a tempo started on one page is the same beat on all of them. The relay keeps nothing: a room exists while someone is in it. Discussion #135; see Study 34 · io.

OSC bridge

A page cannot send or receive UDP, so the relay can do it for it: with --osc it also answers on ws://<host>/osc and passes OSC between the pages and SuperCollider, Max, Pd, TouchOSC, Open Stage Control… (discussion #135). It is meant for your own machine:

npx @kairotic/relay --osc                                  # pages → udp 127.0.0.1:57120 (sclang), udp 57121 → pages
npx @kairotic/relay --osc --osc-out sc=57120 --osc-out max=127.0.0.1:7400 --osc-in 9000

| | | |---|---| | --osc-out name=host:port | where the pages' OSC goes (several allowed; a page picks one by name, the first by default). The relay never sends anywhere else | | --osc-in 57121 | the UDP port where OSC arrives for the pages (--osc-bind 0.0.0.0 to take it from other machines, such as a phone with TouchOSC) | | --oscquery 5678 | the HTTP port where the pages' declared parameters are published as OSCQuery (0: none), for ossia score, Chataigne, TouchDesigner… — add http://<host>:5678 by hand in them (no mDNS) | | --osc-origin url | the sites allowed to use the bridge: https://bonuoq.github.io, http://localhost and http://127.0.0.1 by default. With *, any site you visit could send OSC to your synths |

A page sends JSON frames {"address": "/x", "args": [1, 2.5, "a"], "types": "ifs", "to": "max"} (types and to optional: an integer is i, any other number f, a string s, true/false T/F) and receives {"address", "args", "types", "from", "timetag"?}; a bundle arrives as its messages. Bytes are made with osc.js (OSC 1.0, no dependency).

From https://bonuoq.github.io the page reaches ws://localhost because browsers treat localhost as secure; Chrome may first ask to let the site reach devices on your local network. Safari may refuse it: serve the page from your machine too, or use Chrome or Firefox.

Notes

  • ws 7. GUN's server code expects text frames; ws 8 delivers Buffers that GUN ignores, so the relay accepts connections but passes nothing. package.json pins ws 7 (also as an override).
  • GUN version. The same commit as the browser files in site/vendor/gun/.
  • Hosting. Any host that runs a Node process with WebSockets and a writable folder: a small VPS, Fly.io, Railway, Render (a free instance sleeps and loses its disk; fine for trying, not for keeping works), or a machine at home behind a tunnel. The browser needs wss:// (TLS) when the site is served over https, which these hosts give.
  • What the relay keeps: rooms in clear, solo works encrypted by their owners. Back up radata/.