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

tbrowse

v2.7.0

Published

Embeddable React component for visualizing phylogenetic trees and pluggable data zones.

Downloads

741

Readme

tbrowse

Embeddable React component for visualizing phylogenetic trees with pluggable data zones.

<TBrowse> renders a tree alongside a row-aligned set of zones (Tree, Labels, MSA, custom plug-ins). Tree topology, taxonomy, MSA, gene metadata, and per-node annotations are independent host inputs — TBrowse does no fetching of its own. View state (selection, collapse, prune, swap, zone widths, MSA viewport, search) is a single serializable object that round-trips through URL state via the controlled viewState / onViewStateChange props.

Status

2.0.0 is a complete rewrite of the original component on a fresh React 18 / TypeScript / Zustand stack. The 1.x line on npm ([email protected]) is the previous nwb / React 16 / Redux-Toolkit implementation, preserved at commit b017a74 for archival reference. The 2.0 API is not backwards-compatible with 1.x.

The rewrite is functionally complete: chassis, four built-in zones (Tree / Labels / MSA / Neighborhood), Ensembl REST and Gramene adapters, animated transitions, branch-length compression, gene-family coloring, protein-domain annotations, splice-junction marks, and a nodeOfInterest pivot. See CHANGELOG.md for the migration summary.

Quick start

import { TBrowse, treeZone, labelsZone, msaZone, type Tree, type MSA, type Taxonomy } from 'tbrowse';

const tree: Tree = { rootId: 'n0', nodes: { /* ... */ } };
const taxonomy: Taxonomy = { /* taxId → { scientificName, commonName, ... } */ };
const msa: MSA = { alphabet: 'protein', length: 60, sequences: { /* geneId → string */ } };

<div style={{ width: 900, height: 600 }}>
  <TBrowse
    tree={tree}
    taxonomy={taxonomy}
    msa={msa}
    zones={[treeZone, labelsZone, msaZone]}
  />
</div>

Live Ensembl example

The bundled Vite playground (npm run dev) has a "Load Ensembl tree" button that fetches a real gene tree (BRCA2 — ENSG00000139618) from rest.ensembl.org, runs it through fromEnsemblGeneTree, and renders it pivoted to put human BRCA2 at the top. Demonstrates the entire stack against live data.

import { fromEnsemblGeneTree, computePivotState, TBrowse } from 'tbrowse';

const json = await fetch(
  'https://rest.ensembl.org/genetree/member/id/homo_sapiens/ENSG00000139618?aligned=1&sequence=protein',
  { headers: { Accept: 'application/json' } },
).then((r) => r.json());

const { tree, taxonomy, msa, geneMetadata } = fromEnsemblGeneTree(json);

Development

npm install
npm run dev         # Vite dev server (examples/playground)
npm run typecheck   # tsc --noEmit
npm test            # vitest
npm run build       # library build to dist/

Host inputs

interface TBrowseProps {
  tree: Tree;                          // required
  taxonomy?: Taxonomy;
  msa?: MSA;
  geneMetadata?: GeneMetadata;
  nodeAnnotations?: NodeAnnotation[];
  labelProviders?: LabelProvider[];

  zones: ZoneDefinition[];             // built-ins + plugins
  nodeOfInterest?: string;             // pivot the tree to this gene/node at mount

  // Controlled / uncontrolled view state
  viewState?: ViewState;
  initialViewState?: Partial<ViewState>;
  onViewStateChange?: (next: ViewState) => void;

  theme?: 'light' | 'dark';
  className?: string;
}

Tree.nodes is flat: { id, parentId, distance, isLeaf, taxonomyId?, geneId?, eventType?, bootstrap? }. MSA.sequences is keyed by gene id. The Ensembl adapter (fromEnsemblGeneTree) walks the nested REST response into this normalized shape.

ViewState

The single serializable object that captures everything URL-shareable.

interface ViewState {
  selectedNodeId: NodeId | null;
  collapsedNodeIds: NodeId[];          // internal nodes shown as triangles
  prunedNodeIds: NodeId[];             // subtrees hidden + replaced with stub glyphs
  swappedNodeIds: NodeId[];            // internal nodes whose children render in reversed order
  zones: { id: string; width: number; visible: boolean }[];
  zoneStates: Record<string, unknown>; // per-zone state slot (built-ins use well-known keys)
  search: { field: string; query: string } | null;
}

All chassis interactions (resize, reorder, collapse via tooltip, prune via tooltip, swap, MSA pan/zoom, label-field picker, show/hide) write to this object via onViewStateChange. Persist it to a URL fragment for shareable views.

Built-in zones

| Zone | Id | Default width | |---|---|---| | treeZone | tree | 280px | | labelsZone | labels | 220px | | msaZone | msa | 360px |

The Tree zone supports collapse/expand, prune/regrow, swap children, click-tooltip with contextual actions, internal-node event glyphs (speciation circle / duplication square), proportional-height collapsed-subtree triangles, and animated transitions. Labels supports a configurable field picker (gene id, gene name, gene description, scientific name, common name) plus optional async LabelProvider plug-ins. MSA renders a canvas alignment with a coverage minimap (drag-to-pan), wheel-driven pan + ctrl/shift-zoom, and four built-in color schemes (Plain, Clustal, Hydrophobicity, Nucleotide).

Custom zones implement ZoneDefinition:

interface ZoneDefinition<S = unknown> {
  id: string;
  displayName: string;
  Header: ComponentType<ZoneRenderProps<S>>;
  Body: ComponentType<ZoneRenderProps<S>>;
  defaultWidth: number;
  minWidth: number;
  defaultZoneState: S;
  isAvailable: (data: HostData) => boolean;
}

Both Header and Body receive the same ZoneRenderProps: visibleRows (already collapsed/pruned/swapped), virtualization rowRange, hover/select callbacks, the host's data, and per-zone state plumbing.

Helpers

| Export | What | |---|---| | computeVisibleRows | Pure derivation: (tree, collapsed, pruned, swapped) → VisibleRow[]. | | computeTreeLayout | Pure phylogram layout against a column width. | | computePivotState | Resolve a gene id / node id and return collapse + swap sets that pivot the tree. | | fromEnsemblGeneTree | Convert Ensembl REST gene-tree JSON to TBrowse inputs. | | createStubZone | Build a placeholder zone for development. |

Bundle

ESM + CJS, types via vite-plugin-dts. Peer-deps on react / react-dom only; runtime dep on zustand. Current bundle ~14 kB gzipped (CJS).

Project layout

src/
  TBrowse.tsx, types.ts, store.tsx, treeIndex.ts
  visibleRows.ts        chassis row derivation
  pivot.ts              nodeOfInterest helper
  layout/               grid + virtualization + animation
  zones/
    tree/               SVG branches, glyphs, triangles, tooltip
    labels/             field picker, label-provider cache
    msa/                canvas paint, minimap, color schemes
  adapters/
    ensembl.ts          Ensembl REST → TBrowse inputs
  *.test.ts             vitest unit tests
examples/playground/    Vite dev app (kitchen-sink demo)

License

MIT.