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

@cocorof/graphier

v1.6.1

Published

High-performance graph renderer for React: 3D/2D force layout (Three.js, d3-force-3d) and a 2D overview engine for 100k+ precomputed nodes

Readme

Graphier

High-performance 3D/2D graph renderer for React, built on Three.js with a d3-force-3d layout running in a Web Worker.

npm License

Nodes are drawn as one InstancedMesh and edges as one LineSegments, so a graph costs two draw calls regardless of size. Layout, level of detail, bloom and fog adapt to the node count automatically.

Install

npm install @cocorof/graphier three react react-dom

Peer dependencies: react >= 18, react-dom >= 18, three >= 0.150. The package ships ESM and CJS builds with type declarations.

Quick Start

import { NetworkGraph3D } from "@cocorof/graphier";

const data = {
  nodes: [
    { id: "alice", type: "person", label: "Alice", val: 10 },
    { id: "bob", type: "person", label: "Bob", val: 5 },
    { id: "project-x", type: "repo", label: "Project X", val: 20 },
  ],
  links: [
    { source: "alice", target: "project-x", type: "owns" },
    { source: "bob", target: "project-x", type: "contributes" },
    { source: "alice", target: "bob", type: "follows" },
  ],
};

export default function App() {
  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <NetworkGraph3D data={data} />
    </div>
  );
}

The component fills its container, so give the parent an explicit size. type and group map to theme colors; val controls node size.

Features

  • Web Worker force layout (d3-force-3d) off the main thread; positions survive data changes
  • 3D or flat 2D mode (layout.dimensions: 2), with optional layout.clusterBy ("type" or "group")
  • Nodes render as glowing, bloom-lit rings; star field, nebula backdrop and fog are optional
  • Reheat-free filtering with visibleNodeIds and linkVisibility
  • Click-to-focus, hover neighborhood highlight, N-hop selection highlight
  • Pointer and keyboard navigation (fly, orbit or pan), remappable via renderer.navigation
  • Incremental updates with appendData() (existing positions are kept)
  • Four theme presets (celestial, neon, minimal, paper for light backgrounds) or a custom ThemeConfig
  • Extra components: GraphMinimap, NodeDetailPanel, SubgraphView2D, plus buildSubgraph
  • @cocorof/graphier/analysis: graph statistics with no Three.js dependency

Large overviews: OverviewGraph

NetworkGraph3D simulates its layout in the browser, which is comfortable up to roughly 10 to 20 thousand nodes. For bigger networks, compute the layout once on a server and draw it with OverviewGraph, a 2D WebGL view built for 100k+ nodes and about a million edges:

  • Every node and edge carries the zoom level from which it is drawn. The GPU hides the rest from one uniform, so zooming never rebuilds buffers. Below zoom 0 (a phone showing everything) only the most important nodes remain.
  • Data arrives in chunks ordered by that level, so a phone can stop after the first one or two and a desktop can load all of them. Chunks are appended into preallocated buffers.
  • Hover and click use a spatial grid; labels come from precomputed collision-free levels and are checked again on screen.
  • Frames are drawn only when something changed. If frames get slow during interaction, detail drops a step.
import { OverviewGraph, decodeChunk, type OverviewChunk, type OverviewMeta } from "@cocorof/graphier";

const meta: OverviewMeta = await (await fetch("/data/meta.json")).json();
const chunks: OverviewChunk[] = [];
for (const c of meta.chunks.slice(0, 2)) {
  const [bin, extra] = await Promise.all([fetch(`/data/${c.name}.bin`).then((r) => r.arrayBuffer()), fetch(`/data/${c.name}.json`).then((r) => r.json())]);
  chunks.push(decodeChunk(bin, extra));
}

<OverviewGraph meta={meta} chunks={chunks} theme="paper" colorBy="cluster" onSelect={(i) => console.log(i)} style={{ width: "100%", height: 600 }} />

The chunk format (GNC1) is documented in src/overview/format.ts. Ref methods: flyTo, flyToRef, select, fit, zoomBy, getView, screenshot. OverviewEngine is the same renderer without React.

To open a detailed view seeded from overview positions, pass the positions on the nodes and set layout={{ preset: "seed", initialAlpha: 0.25 }} (or "pin" to keep them exactly) on NetworkGraph3D.

NetworkGraph3D props

| Prop | Description | |------|-------------| | data | { nodes, links } (required) | | theme | Preset name or ThemeConfig (default "celestial") | | style | StyleConfig: node size range, edge opacity, bloom, star field, nebula, fog, labels, flySpeed, autoOrbit | | layout | LayoutConfig: charge, linkDistance, alphaDecay, velocityDecay, spreadFactor, settledThreshold, dimensions, clusterBy, clusterStrength, preset, initialAlpha | | renderer | RendererConfig: antialias, pixelRatioMax, cameraMode, navigation | | selectedNodeId, highlightHops | Controlled selection and highlight radius (default 3) | | visibleNodeIds, linkVisibility | Filters that never re-run the layout | | enableNodeDrag, clickToFocus, hoverHighlight, hoverHighlightHops | Interaction options | | labelFormatter, nodeValueAccessor | Custom label text and node size | | onNodeClick, onNodeDoubleClick, onNodeHover, onContextMenu, onLinkClick, onLinkHover, onNodeDrag, onNodeDragEnd, onLayoutSettled, onLayoutTick | Event callbacks |

Defaults for every option are in USAGE.md and in the exported DEFAULT_STYLE / DEFAULT_LAYOUT.

Ref API

import { useRef } from "react";
import { NetworkGraph3D, GraphMinimap, type NetworkGraph3DRef } from "@cocorof/graphier";

const ref = useRef<NetworkGraph3DRef>(null);

<NetworkGraph3D ref={ref} data={data} layout={{ dimensions: 2, clusterBy: "type" }} theme="paper" />
<GraphMinimap graphRef={ref} width={200} height={140} />

ref.current?.focusNode("alice", 1200);
ref.current?.zoomToFit(800, 100);
ref.current?.appendData(newNodes, newLinks); // returns number of nodes added
const png = ref.current?.captureScreenshot(); // PNG data URL

Methods: cameraPosition, zoomToFit, zoomIn, zoomOut, focusNode, appendData, reheatLayout, panTo, captureScreenshot, hasUserAdjustedCamera, getScene, getRenderer, getCamera, getGraphSnapshot, getViewportRect.

Analysis

import { analyzeGraph } from "@cocorof/graphier/analysis";

const stats = analyzeGraph(data);
// nodeCount, linkCount, density, avgDegree, maxDegree, minDegree, degreeMap,
// nodesByType, linksByType, topByDegree(n)

Keyboard

Keys apply while the graph container is focused. In fly mode (default in 3D) Z/X thrust forward/back and arrows or WASD steer; in orbit mode Z/X zoom and arrows orbit; in 2D (or keyboard: "pan") arrows/WASD pan and Z/X zoom. Escape deselects.

Next.js / SSR

The renderer needs the browser. Load it client-only:

"use client";
import dynamic from "next/dynamic";
const GraphView = dynamic(() => import("./GraphView"), { ssr: false });
// next.config.js
module.exports = { transpilePackages: ["@cocorof/graphier"] };

Development

npm install
npm run typecheck  # tsc --noEmit
npm run build      # regenerate inlined worker, typecheck, vite build -> dist/

src/layout/worker-inline.ts is generated by scripts/build-worker.js from the worker source; rerun npm run build after changing the worker. The repository has no automated test suite.

Documentation

License

Apache License 2.0. See LICENSE.