CLI tool
npmgraph/npmgraph avatar
npmgraph/npmgraph

npmgraph: an npm dependency explorer whose whole configuration is a shareable URL

A tool for exploring NPM modules and dependencies

797 stars72 forksTypeScriptMIT

At a glance

What is it?
npmgraph draws the dependency graph of an npm package, and the interesting part is that the configuration lives in the URL, so a link is the whole setup. The search term is a query parameter, and everything else is encoded in the hash, including a JSON payload that lets you graph private packages.
Who is it for?
npmgraph fits a developer who needs to see what a package actually pulls in, or to share that view with a colleague, because the URL is the configuration and the graph is reproducible from it. It does not fit a team that needs a durable inventory of its dependencies over time, and it does not replace a lock file.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The URL is the configuration, and that is the whole design

npmgraph is a tool for exploring npm modules and dependencies, available online at npmgraph.js.org, and the README leads with a pointer to a newer npmgraph CLI in a separate repository for people who want the work locally.

The interesting decision is in the URL API. Diagrams are configured using URL parameters, and with the exception of one parameter these are not search parameters: they are stored in the location hash, using normal URL query parameter encoding.

That distinction is small in the code and large in the consequence. A search parameter is sent to the server with every request, so a diagram configuration expressed that way would travel to the service on every page load. A hash parameter never leaves the browser. It also means a graph URL is self contained: there is no server side session, no saved diagram, no account. Whatever you are looking at, the link reproduces.

The single exception is the q parameter, which is a genuine search parameter and takes a comma-separated list of module names or URLs. The rest of the configuration sits beside it in the hash, so the module you are graphing is visible in the query string and everything else is in the fragment.

For a tool whose output is a picture of a dependency tree, that is a sensible choice. Sharing a link shares the exact view, including which dependency types are included and which subtrees are collapsed.

Colouring by bus factor or by how outdated a version is

The colour parameter is described in the README as the colorization mode, also known as the Colorize by field in the user interface, and it supports three values that answer three different questions about a dependency tree.

moduleType colours the graph nodes by the package.json#type value, so you can see at a glance which packages are ES modules, which are CommonJS and which are something else. That is a question you ask when a bundler or a runtime complains about module format.

bus colours by the number of maintainers, and the README links the definition to the bus factor. This is the risk view: a package with one maintainer is a package whose unmaintained status is one person's decision away.

outdated colours by the degree of version outdated-ness, which is the maintenance view: how far behind the published version is.

Alongside colour, the graph has a set of structural parameters. collapse takes a comma-separated list of modules to collapse, so that a subtree can be folded away when it is not the point of the diagram. deps takes a comma-separated list of dependency types to include, with the important asymmetry that devDependencies are only included for top-level modules while peerDependencies are included across the graph when enabled, and dependencies always included. hide hides the inspector panel, and sizing scales the modules to reflect their unpacked size.

The select parameter is the one that turns a picture into a query tool. Its values are exact with a module key, name with a module name across all versions, license with a licence string, and maintainer with a maintainer name, which means you can ask for the graph of everything under one licence, or everything maintained by one person, and read the answer as a picture.

Private packages travel as a JSON payload in the hash

The packages parameter is the answer to a question that would otherwise stop the tool dead: how do you graph a module that is not on the public registry. It takes a JSON-encoded array of package.json contents for any custom or proprietary modules included in the graph.

The README shows the whole thing generated in code, and the shape of that code is the documentation. Two package.json objects are defined, one for a module called foo at version 1.2.3 depending on send and bar, and one for bar at 3.2.1 depending on debug. A URL is then built and the packages array is attached to its hash:

js
const fooPackage = {
  // package.json for "foo"
  name: 'foo',
  version: '1.2.3',
  dependencies: { send: '0.18.0', bar: '3.2.1' },
};
const barPackage = {
  // package.json for "bar"
  name: 'bar',
  version: '3.2.1',
  dependencies: { debug: '2.6.9' },
};

const url = new URL('https://npmgraph.js.org');

The rest of the example sets the hash from a URLSearchParams with the packages key, sets the q parameter to the name and version of the root module, and returns the URL.

Two things follow. The private package data never leaves the browser, because it lives in the fragment, which is not transmitted to the server. And because the payload is just package.json contents, the graph of a private module is only as good as the metadata you paste, including the version pins inside its dependencies, which is why the example spells out exact versions.

The repository ships a sample of this shape in samples/ghost-dependencies.json, and the presence of that file suggests the private module case is a normal one rather than an afterthought.

Running the site locally is four commands

NPMGraph is built with vite, and the README gives the local development path directly:

shell
$ git clone https://github.com/npmgraph/npmgraph.git
$ cd npmgraph
$ npm install
$ npm start

That is a conventional Vite project, and the scripts in package.json show the rest of the workflow. The start script is vite, the build script is vite build, and there is a fetch-licenses script that runs node scripts/fetch_licenses.js, which is the piece that pulls licence text for the packages in the graph.

The manifest also shows the runtime expectation. The devEngines block asks for node at version 24.0.0 or above, with onFail set to warn, so a mismatch warns rather than blocking.

The dependency list explains how the picture is drawn. Layout comes from @hpcc-js/wasm-graphviz, which is Graphviz compiled to WebAssembly, and the graph structure comes from d3-hierarchy with d3-selection for the DOM work. The interface uses React 19 with @visx for axes, grids and scales, and react-zoom-pan-hing for panning and zooming the canvas. The remaining packages are the small pieces that a real application accumulates: react-error-boundary and @bugsnag/js for failures, hosted-git-info for repository metadata, module-replacements and filter-altered-clicks for the resolution logic, select-dom for selection, simplur for a fake data set and verkit for versioning.

The test setup is worth noting because it is unusual for a front end project: the test script runs format:check, lint, types, test:unit and build in parallel, the unit tests are a vitest project, and there is a separate smoke project with a smoke.test.ts file at the root.

Where npmgraph is the wrong tool

The first wrong fit is a durable inventory. A graph you look at once and share as a link is a diagram, not a record. If you need to know what your dependencies were on a given date, or to detect a new package arriving in a transitive tree, you need something that runs on a schedule and writes down what it found, and npmgraph is not that. The samples/ghost-dependencies.json file in the repository is a snapshot of a sort, not a monitor.

The second is a project that needs the resolved tree rather than the declared one. The graph is built from package.json metadata, which is what packages declare, not what the registry resolved for your particular tree. A lock file remains the authority on what you actually installed, and the two can disagree.

The third is an offline or restricted network. The hosted service resolves packages from the public registry, and while the private package payload is handled in the browser, the public part of the graph still needs the registry. The local development path exists for that case, but then you own the hosting.

The fourth is a security review. A dependency graph tells you the shape of the tree, and the bus factor colouring gives you a rough risk signal per node, but it is not an audit of what any package does. The tool's own scope is visualisation.

The fifth is a codebase that is not npm. This is an npm tool, it reads package.json, and the colouring modes are built around the package.json#type field and the bus factor of npm maintainers.

On the state of the project: it is MIT licensed, with the LICENSE file at the root of the repository, the author is Robert Kieffer, and the funding links point at the two GitHub sponsors pages for broofa and fregante. The manifest version is 3.1.1, the repository has no GitHub releases, and the last push was on 2026-10-20 with the repository not archived, so the deployment at npmgraph.js.org is what people are actually using.

Editorial conclusion

npmgraph fits a developer who needs to see what a package actually pulls in, or to share that view with a colleague, because the URL is the configuration and the graph is reproducible from it. It does not fit a team that needs a durable inventory of its dependencies over time, and it does not replace a lock file. Before relying on a graph, remember that the service resolves packages from the public registry, so a private package only appears if you supply its package.json yourself.

Frequently asked questions

What is npmgraph?

It is a tool for exploring npm modules and dependencies, available online at npmgraph.js.org, which draws the dependency graph of a package and lets you filter, colour and select within it. A separate npmgraph CLI project exists for running the work locally.

How do I configure a dependency graph in npmgraph?

The module list goes in the q search parameter, and every other option, such as collapse, color, deps, hide, packages, select and sizing, is stored in the location hash using normal query parameter encoding, so the configuration never leaves the browser.

Can npmgraph show private or proprietary packages?

Yes, through the packages hash parameter, which takes a JSON-encoded array of package.json contents for custom modules. The README shows a script that builds such a URL with a foo package and a bar package in a local graph.

What can I colour nodes by in npmgraph?

Three modes are documented: moduleType, which uses the package.json#type value, bus, which uses the number of maintainers, and outdated, which uses the degree to which the version is outdated.

How do I run npmgraph locally?

The project is built with vite. Clone the repository, change into the directory, run npm install and then npm start, and the devEngines block asks for Node 24.0.0 or newer.

Official sources

  1. Issues
  2. License: MIT
  3. npmgraph/npmgraph on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/npmgraph-npmgraph.svg)](https://hysenlabs.com/projects/npmgraph-npmgraph)

Was this useful?