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

@a2f0/dnbm

v0.4.2

Published

A dark drum and bass sequencer, mixer and player with a WebAssembly audio engine, ready to embed in a page

Readme

dnbm

A dark drum and bass sequencer and mixer in the browser, at dnbm.a2f0.net. Program patterns on a step grid, arrange them into a song, mix them with per-track filters, drive and sends, and save songs as plain text that diffs and merges cleanly in Git.

The sound comes from a Rust engine compiled to WebAssembly and run in an AudioWorklet. Every drum and bass sound is synthesized, not sampled; steps land on the exact sample they fall on; and the same engine renders WAV files offline. A song sounds the same in the browser, in an export and from the command line.

Run it

mise install                      # Bun, Node, ShellCheck and wasm-opt (see .mise.toml)
bun install
sh scripts/git/install-hooks.sh   # once per clone
bun run dev                       # http://localhost:8174

Rust comes from rustup, which installs the toolchain and WebAssembly target pinned in rust-toolchain.toml on first use.

The editor opens on Undertow, a 172 BPM roller in F minor: syncopated sub and reese bass, dry backbeats, ghost snares and sparse, filtered dub echoes. Its 36 bars move from a short intro through four-bar variations, a half-time break and a heavier return. Press space to play. The browser restores your last session; choose Undertow from examples to reload the bundled song. The same menu holds ten darker songs, from Bathyal's slow pressure and Oubliette's bare cell to Corrosion's industrial grind and Sever's techstep cuts, each longer than Undertow and all built from the same synthesized kit: drones and stabs come from the pad instrument, detuned saw pairs an interval apart under a slow, resonant filter.

Click an arrangement slot to start there, or choose loop to work on one pattern. follow keeps the grid on the playing pattern; selecting another pattern during song playback turns follow off so you can edit ahead. Muted channels and channels excluded by solo dim in the mixer. The master holds its highest peak in dBFS; click that reading to reset it, or start playback for a fresh reading.

Player

dnbm.a2f0.net/player/ plays the example songs as a playlist, after the desktop players of old: elapsed or remaining time, a spectrum, seek, shuffle, repeat and volume, with Z, X, C, V and B for previous, play, pause, stop and next. It plays through the same engine as the editor and edits nothing. Other pages embed it with mountDnbmPlayer from the package, passing any list of song files as the playlist.

Songs

Songs are .dnbm.json files. Each pattern row is one line, so changing a step changes one line of the file:

"rows": {
  "kick": "X... .... ..X. .... | ..X. .... ..X. ....",
  "snare": ".... X... .... X... | .... X... .... X...",
  "reese": "F-1 --- --- ---  --- --- ... F-1  --- ... F-1 ---  F#1 --- --- ... | ..."
}

In Chromium, Save writes back to the file you opened, so a song in a Git checkout can be edited, saved and committed in place. The song format describes every field.

bun run render songs/undertow.dnbm.json   # render to undertow.wav (24-bit, 48 kHz)
bun run songs:fmt                         # rewrite songs/ canonically
bun run songs:check                       # fail on an invalid or non-canonical song

Package

dnbm is also published to npm as @a2f0/dnbm, to embed the whole app in another page or app, such as a mini-app window:

import { copyDnbmAssets } from "@a2f0/dnbm/build";   // in a build script
await copyDnbmAssets("./public/dnbm");

import { mountDnbm } from "@a2f0/dnbm";              // in the browser
const dnbm = mountDnbm(container, { assetsUrl: "/dnbm/" });
await dnbm.ready;                                     // it shows

import { mountDnbmPlayer } from "@a2f0/dnbm";        // or just the player
const player = mountDnbmPlayer(container, { assetsUrl: "/dnbm/", songs });

The app renders in the host's own document, inside a shadow root that keeps its styles and the host's apart, and takes only the keys pressed inside it. A host's own controls, such as a window's menus and toolbar, can drive it: each instance runs commands (dnbm.run("save")), reports its state (playing, the song's title, unsaved changes, which commands are available) and tells subscribers when it changes, and actions: false leaves out the app's own buttons for those commands. The package guide covers embedding and releases.

Layout

| Path | What | | --- | --- | | packages/synth/ | The shared synthesizer: the Rust audio engine (engine/), its AudioWorklet host, and the song format | | packages/sequencer/ | The editor and mixer (TypeScript and DOM) | | src/ | The npm package's entrypoints (mountDnbm, mountDnbmPlayer, copyDnbmAssets), and the shell that mounts an app into a shadow root | | packages/player/ | A playlist player that plays songs through the same synthesizer | | test/ | Repository-wide tests: the packed npm package, and the greys-only rule | | songs/ | Example songs | | scripts/ | Build, dev server, WAV render, song formatter, git hooks and checks | | docs/ | Song format, architecture, package, deploying |

Development

bun run check   # everything CI checks; the pre-push hook runs it too; needs Google Chrome
bun run test    # build the engine, then the TypeScript tests
bun run engine:check   # rustfmt, clippy and cargo test
bun run fix     # format TypeScript, Rust and songs

See dependency maintenance for upgrade procedures and active constraints. Coding agents follow AGENTS.md.