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

munchkeen

v0.1.0

Published

Solid-first interactive graph exploration toolkit with Cytoscape.js as the first renderer

Readme

munchkeen

pnpm codecov

munchkeen is a Solid-first interactive graph exploration toolkit.

In v1, Cytoscape.js is the first renderer adapter and the first production renderer, but the library is architected around a renderer-neutral graph, projection, layout, scene, and renderer-command pipeline.

Direction

munchkeen is not intended to be only a thin Cytoscape wrapper.

The package has three public entrypoints:

  • munchkeen: the default Solid Graph integration surface
  • munchkeen/core: the pure graph pipeline and state-transition surface
  • munchkeen/cytoscape: the typed Cytoscape integration and escape hatch surface

The default root entrypoint stays friendly and intentionally leaves low-level renderer session typing opaque. If you want to work directly with the pure pipeline, use munchkeen/core. If you want typed Cytoscape sessions, command timing, or adapter-level helpers, use munchkeen/cytoscape.

Install

Install it:

npm i munchkeen
# or
yarn add munchkeen
# or
pnpm add munchkeen

Entry Points

munchkeen

Use the default entrypoint when you want a controlled Solid graph component with the built-in Cytoscape renderer.

import { Graph, edgeId, nodeId } from "munchkeen";

const ada = nodeId("ada");
const charles = nodeId("charles");
const collaborates = edgeId("collaborates");

<Graph
  graph={{
    nodes: [
      { id: ada, label: "Ada Lovelace" },
      { id: charles, label: "Charles Babbage" },
    ],
    edges: [{ id: collaborates, source: ada, target: charles, label: "collaborates" }],
  }}
  layout={{ kind: "breadthfirst", root: ada }}
  view={{
    focus: ada,
    neighborhood: { radius: 1, direction: "both" },
  }}
/>;

Reference example: examples/minimal-graph.tsx

munchkeen/core

Use the core entrypoint when you want to drive validation, projection, layout, scene construction, and diffing yourself.

import {
  buildRenderScene,
  diffScene,
  isLeft,
  projectGraph,
  runLayout,
  validateGraph,
} from "munchkeen/core";

const validated = validateGraph(graph);

if (isLeft(validated)) {
  throw new Error(validated.left.map((error) => error.message).join(", "));
}

const projected = projectGraph({ graph: validated.right });
const laidOut = runLayout({ graph: projected.right });
const scene = buildRenderScene({ graph: laidOut.right });
const commands = diffScene(undefined, scene);

Reference example: examples/core-pipeline.ts

munchkeen/cytoscape

Use the Cytoscape entrypoint when you want the typed adapter surface directly.

import { createCytoscapeRenderer } from "munchkeen/cytoscape";

const renderer = createCytoscapeRenderer();
const created = renderer.createSession();

if (created._tag === "Right") {
  created.right.syncViewport();
}

This is the companion surface for low-level renderer authoring. The root GraphRenderer type intentionally stays more opaque.

Examples

Tests

Run the client and SSR test suites:

pnpm test

Generate a local coverage report:

pnpm test:coverage

Vitest writes coverage artifacts to coverage/.

Documentation Playground

The repository includes a docs playground built from the runnable examples in examples/.

pnpm docs:dev

That starts the Vite app in dev/, which now acts as the local documentation surface for the package.

To produce the static docs bundle:

pnpm docs:build

The output is written to dev/dist.

dev/dist can be published to any static hosting provider.

Pure Core vs Adapter Escape Hatches

Pure core concepts live in munchkeen/core:

  • graph data and branded ids
  • view transitions
  • validation
  • projection
  • pure layouts
  • semantic scene construction
  • scene diffing into render commands

Renderer-specific concerns live outside the pure core:

  • DOM attachment
  • viewport synchronization
  • Cytoscape stylesheet generation
  • Cytoscape event wiring
  • command execution timing
  • Cytoscape-native layouts

That split is deliberate. The pure pipeline owns semantic graph state. Renderers interpret semantic commands at the boundary.

Current Limitations

  • Cytoscape is the only production renderer today.
  • The root Graph component is browser-oriented because it owns a DOM viewport.
  • The pure core is first-class through munchkeen/core, but advanced staged types are still a more expert-facing surface than the root component API.
  • Renderer timing currently reports adapter-local batch duration and frame-budget usage, but it does not yet provide a full live benchmark dashboard for minimal diff versus full replace outside the development harness.