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

@here.build/plexus

v0.9.5

Published

Reactive state management with automatic replication: make TypeScript classes sync across clients via Yjs CRDT.

Readme

@here.build/plexus

i-cant-believe-its-not-local.png

Reactive state management with automatic replication in familiar style. Just make TypeScript classes sync across clients via most popular JS CRDT protocol and one of most mature T-FRP JS engines.

npm install @here.build/plexus

Who this is for

Plexus is the layer that makes your TypeScript classes the CRDT — MobX for reactivity, any Yjs provider you already trust.

Yjs is great CRDT engine - but it forces to build the data model around its own primitives. Plexus offers the opposite - keep your data model, or build one from scratch in TypeScript, and make it CRDT-backed without changing anything at all.

If you do not want to design your whole application around Y.Array and Y.Map, this is for you.

Quick Start

You will need to use TypeScript with stage-3 decorators specifically.

To enable stage-3, you need to have experimentalDecorators in tsconfig.json disabled.

import * as Y from "yjs";
import { Plexus, PlexusModel, syncing } from "@here.build/plexus";

// you will need only three entities - @syncing.* to annotate... 
@syncing("Counter")
//  ...PlexusModel to extend from...
class Counter extends PlexusModel {
  @syncing accessor count = 0;
}
//  ...and Plexus to connect the document to the model.
const plexus = Plexus.bootstrap(new Counter());
//  And it's just synced to all connected clients
plexus.root.count++;

Connect any Yjs provider — y-websocket, y-webrtc, Hocuspocus, PartyKit, Liveblocks, y-sweet — for real-time sync. Same doc as bootstrap:

import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";

const doc = new Y.Doc();
const provider = new WebsocketProvider("wss://your-server", "room", doc);
Plexus.bootstrap(new Counter(), doc.guid, doc);

Joining a room that already has a root is connect, not bootstrap. Those are separate flows: bootstrap produces the initial root (not an authority); connect never does — bootstrap vs connect.

Rich Data Structures and Contagious Materialization

Plexus provides parent-child relations represented, support of lists (arrays), records, maps (with structural keys) and seamless mobx integration.

What is does not provide is manual sync management - because it produce structural sync guarantees. You push, add, or set models - rest is done automatically. The moment model gets related to the materialized entity, it gets represented inside CRDT document, along with all its own related models - contagiously.

import { autorun, computed } from "mobx";
import { Plexus, PlexusModel, syncing } from "@here.build/plexus";

@syncing("Task")
class Task extends PlexusModel<Project> {
  @syncing accessor title = "";
  @syncing accessor done = false;
}

@syncing("Project")
class Project extends PlexusModel {
  @syncing accessor name = "";
  @syncing.list accessor labels: string[];
  @syncing.set accessor tags: Set<string>;
  @syncing.record accessor meta: Record<string, string>;
  @syncing.map accessor scores: Map<[team: string, player: number], number>;
  @syncing.child.list accessor tasks: Task[];

  // local derivation, global inputs — peers writing .done invalidate this too
  @computed get openCount() {
    return this.tasks.filter((t) => !t.done).length;
  }
}

const plexus = Plexus.bootstrap(new Project({ name: "ship" }));
const root = plexus.root;

autorun(() => {
  console.log(`${root.name}: ${root.openCount} open`);
});

const task = new Task({ title: "write the demo" }); // no doc
root.tasks.push(task); // now it is — peers have the Task
root.labels.push("v1");
root.tags.add("urgent");
root.meta.area = "core";
root.scores.set(task.title, 10);
task.done = true; // computed updates; so do peers

Docs

  • bootstrap — blank doc writes the seed; prefilled doc uses connect
  • fields@syncing field kinds, ownership vs reference
  • shape — constructors and inheritance
  • lifecycle — materialization is contagious; identity, detach, clone
  • time — MobX, @syncing.action, undo
  • findloadEntity, getAllOfType, parentsOf
  • goodies — virtual maps, declare, lazy containers
  • awareness — presence
  • walk — schema-aware tree walk
  • errors — error types
  • api — API wrap-up
  • internals/internals

License

MIT.