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

@mizansec/ogjs

v0.5.4

Published

Ogjs — high-performance, large-scale graph visualization. GPU force layout in shaders, WebGL2 instanced rendering, grouping/filtering/timeline/geo/annotations, undo-redo, React/Vue/Svelte wrappers.

Readme

Ogjs

High-performance, large-scale interactive graph visualization for the web.

Capability status and open work remain in a private roadmap until publication.

Ogjs is built for large interactive graphs in the browser around three ideas:

  1. Structure-of-Arrays core — every node/edge attribute lives in a flat typed array. No per-element objects, no GC pressure, cache-friendly hot paths for layout, picking, and GPU upload.
  2. WebGL2 instanced rendering with a shared position texture — the graph body draws through bounded instanced passes. Node positions are uploaded once per frame into a single RGBA32F texture that both the node and edge shaders sample via texelFetch, so per-frame upload cost is one texSubImage2D regardless of edge count.
  3. Worker-based Barnes-Hut layout — the force simulation runs in a Web Worker over transferable buffers and streams position frames back. The main thread never blocks; the graph animates live while it settles.

Reproducible performance measurement

Run the performance lab on the target device. Its four tasks measure clustered, degree-hub, hub-and-spoke, or uniform workloads, visibly arrange with the CPU worker or GPU path, filter/highlight, and exercise up to 150 visual groups with explicit CPU timing and live node/edge counts. The motion check reports observed frame intervals rather than derived FPS. The measurement task supports up to 1M nodes and 2M edges, combines CPU submission with GPU timer-query duration for each measured frame, and downloads a versioned JSON report containing build time, median/p95 frame time, picking throughput, worker/GPU layout time, allocated typed-array bytes, viewport, and device capabilities. npm run evidence:performance compares a fresh run with the checked-in macOS/headless-Chrome/SwiftShader profile and rejects incompatible environments or regressions. It is a named regression profile, not a universal hardware speed claim.

For competitive evidence, the dedicated certification harness captures five independent Ogjs and licensed-reference runs at 10k, 50k, 100k, 250k, 500k, and 1M nodes in matched browser sessions with a recorded cooldown. It refuses a superior verdict for incomplete ladders, software renderers, mismatched machines/browsers/viewports, missing metrics, or gains below the chosen threshold. See performance certification.

Quick start

The npm package ships JavaScript and TypeScript declarations only. Applications self-host fonts, icons, images, maps, and other content assets.

import { Ogjs } from 'ogjs';

const og = new Ogjs({ container: '#viz' });

og.addNodes([
  { id: 'a', label: 'Alice', size: 8, color: '#4f8cff' },
  { id: 'b', label: 'Bob' },
]);
og.addEdges([{ source: 'a', target: 'b' }]);

// rule-based styling, evaluated once, written into typed arrays
og.styles.addNodeRule(({ degree }) => ({ size: 4 + Math.sqrt(degree) }));

// OGJS chooses a suitable existing layout, animates it, and frames the result
await og.arrange();

og.on('nodeclick', (e) => console.log('clicked', og.graph.getNodeId(e.nodeIndex)));
const hit = og.hitTest(320, 180); // canvas-local screen coordinates

// one coordinated node/edge tween; invalid ids or edge indices are ignored
await og.animate({
  edgeIndices: [0],
  edgeWidth: [4],
  edgeColor: ['#ef4444ff'],
}, 300, 'quadraticInOut');

Advanced capabilities

The advanced-capabilities guide covers the shared primitives behind Ogjs's editing, analysis, temporal, geographic, and evidence workflows. Each capability has a runnable browser example.

  • Stable editing: stable relationship IDs, rollback-safe synchronous transactions, and grouped undo (run).
  • Editing and edge presentation: validated gestures, deterministic routes, captions, badges, outlines, halos, and pulse (run).
  • Worker insights: cancellable weighted or unweighted centrality, spanning-forest, shell-layer, and multilevel or Leiden community jobs over stable snapshots (run).
  • Temporal playback: node and relationship intervals, atomic multi-window queries, exact seek, trailing windows, grouped lanes, adaptive detail/aggregate views, range selection, and playback (query controls; playback).
  • Geographic investigation: public TopoJSON atlas decoding, self-hosted raster, GeoJSON/MVT feature sources, heat, graph clustering, and spatial queries through one camera; wrapping references keep lines and polygons crossing the antimeridian from spanning the world, reject rings that wind around it more than once, and keep active static vectors editable in SVG (run).
  • Measured evidence: portable correctness plus compatible-profile visual and performance comparisons (run).
  • Projection pipeline: named transactional node and edge fields reused by filters and styles (run).
  • Helm controls: fuzzy node search, semantic legends, and operation progress in one accessible, mountable surface (run).
  • Hierarchy workbench: promote a node or an edge, change flow and spacing, rank sibling lanes without splitting branches, and pack a generated five-level hierarchy and companion components without overlap (run).
  • Progressive exploration: reveal retained branches, fold at stable zoom bands, and compose atomic structural stages (drilldown; zoom folding).
  • Annotation authoring: draw, select, align, resize, style, duplicate, and export persistent graph markup from an optional entry point (run).

API overview

| Area | Methods | |---|---| | Data | stable node/edge IDs; addNodes/addEdges, updateNode/updateEdge, removeNodes/removeEdge, atomic edit(label, apply), setGraph, clear, expand | | Layouts | layouts.forceGPU() (GPU), layouts.force() (worker), size-aware hierarchical, radial, scoped circular / track / temporal / orbit / settleSpacing, retained temporal guides, grid, random, animatedLayouts.*, transitionLayout(apply, { fit }), stop() | | Animation | animate(...) for one attribute tween; animateKeyframes(frames, { signal?, onStep? }) for sequential attribute/layout/camera frames with optional delayed camera motion | | Styling | styles.addNodeRule/addEdgeRule — node marks/images, weighted dial parts with optional donut inset, beacon signal rate, plus per-edge width, color, curvature, dash, arrow, label, badge, outline, halo, pulse, and hidden state; deeply frozen prismPack light/dark tokens and createPrismLegend() | | Editing | forge.join/retarget/scale/rename/grid/acceptDrops/onChange, shared validation, Escape cancellation, atomic undo | | Transformations | atomic ordered fold/spawn/absorb stages, zoom bands, groupBy/ungroup, composable addFilter/addEdgeFilter/clearFilters, contained groupVisually/growVisualGroup/nestVisualGroups, and retained activation via trailGuide and og.unfold | | Projections | projections.defineNode/defineEdge, nodeValue/edgeValue, explicit refresh() after data changes | | Algorithms | paths/traversal/components plus cancellable worker insights.run() for weighted or unweighted strength degree, positive-distance closeness and betweenness, spanning forests, shell layers, and deterministic multilevel or opt-in Leiden communities | | Timeline | timeline.setIntervals/setLanes/setBrush/setViewport/setWindow/setQueries/clearQueries/seek/play/pause/onChange, timeline.state, mountTimeline() — node/edge lifespans, labelled lanes, adaptive event/occupancy views, visual range selection, explicit filtering, playback, and settled UI state | | Geo | createAtlasSource for validated, offline TopoJSON cartography; custom GeoReference; raster XYZ tiles; geo.enable; geo.vectors.set/fit/query/clear; geo.tiles.set/refresh/clear for GeoJSON or MVT sources; geo.heat; geo.clusters.enable/disable/clear; instance projection API | | Contours | contours.set/show/hide/clear/visible — validated scalar grids, ordered line levels, shared camera, and PNG/PDF composition | | Annotations | annotations.add/update/remove/toJSON/fromJSON/toSVG — text/rect/arrow/polygon/circle/callout; node circles and callouts follow layouts; optional @mizansec/ogjs/markup authoring | | History | history.undo/redo (⌘Z/⇧⌘Z), atomic transactions, custom commands via history.run, and settled toolbar state through history.state / history.onChange | | Selection | hitTest(screenX, screenY), setSelected, lasso.select() (freehand), getSelected, getVisible, clearSelection | | Controls | mountHelm({ host?, searchText?, onChoose?, settings?, fullscreen?, grid?, cursor? }), unmountHelm(); settings, search, legend, progress, native fullscreen, cursor, and export-aware grid helpers | | Export | Browser: export.png/svg/pdf/json/csv/graphml/gexf/xlsx(); PNG/PDF accept selection/rectangle crop, padding, and text watermark options. Node: new Graph(), new Camera(), and toSVG(graph, camera) without DOM or WebGL; legacy excel() is SpreadsheetML .xls | | Events | nodehover/out/click/dblclick/activate, edgehover/out/click, drag, selectionchanged, click, viewchanged, animate, layoutstart/computed/end | | Wrappers | BindingKit shared lifecycle; React (createOgjsComponent), Vue 3 (createOgjsVueComponent), Svelte (use:ogjs), and the Angular 21.2.20 AOT recipe in recipes/angular/ | | Notebooks | @mizansec/ogjs/notebook versioned document bridge; separate ogjs-notebook anywidget package | | Language bridge | One protocol-1 graph document from JavaScript/TypeScript, Python, Java, C#, Go, PHP, or Rust; five native recipes execute in verify:languages | | Application adapters | Stable events and ids for app-owned collaboration, atomic edits for reviewed model results, and Strata surfaces for app-owned Canvas2D/PixiJS/Three.js/regl/MapLibre/Deck.gl runtimes |

import { BindingKit } from '@mizansec/ogjs';

const binding = new BindingKit({
  nodes,
  edges,
  events: { nodeclick: (event, og) => inspect(og, event.nodeIndex) },
});
binding.mount(host);
binding.update({ nodes: nextNodes, edges: nextEdges });
binding.destroy();

BindingKit owns the instance it creates. Pass instance instead of options to bind an existing instance without transferring ownership. React, Vue, and Svelte entry points use this same lifecycle, including event replacement, option-driven recreation, SSR-safe construction, and deterministic cleanup.

The Angular 21.2.20 AOT recipe uses the root BindingKit directly and is verified from the packed library by npm run verify:angular. The consumer runs without Zone.js and proves Angular-controlled teardown. Ogjs ships no Angular runtime entry point or Angular dependency.

Collaboration services, identity, persistence, model inference, and third-party canvas engines remain application-owned. The application adapter lab shows the smallest supported seams: stable selection events, one validated undoable edit, and node-anchored risk annotations. Use Strata only when an application runtime genuinely needs its own canvas.

Jupyter and anywidget

The notebook bridge is a dedicated subpath, so importing the root package does not load notebook code:

import { NotebookPort } from '@mizansec/ogjs/notebook';

const port = new NotebookPort(host, { onEvent: (event) => publish(event) });
await port.update({
  protocol: 1,
  id: 'risk-notebook',
  revision: 1,
  graph: { nodes, edges }, // explicit stable node and edge ids
  layout: { kind: 'hierarchical' },
  fit: 'initial',
});
port.dispose();

The separate Python package wraps the same document contract:

from ogjs_notebook import OgjsWidget

view = OgjsWidget({"nodes": nodes, "edges": edges}, port_id="risk-notebook")
view.layout("hierarchical", flow="south")
view.group_by("team")
view

Graph, layout, grouping, options, and standard node/edge style fields are validated before revision state changes. The wheel carries a local JavaScript bundle and makes no CDN request; notebook hosts and anywidget remain external dependencies.

og.layouts.hierarchical({
  roots: ['gateway'],
  flow: 'east',
  components: 'across',
  layerGap: 72,
  nodeGap: 24,
  componentGap: 48,
  rankBy: ({ data }) => (data as { priority: number }).priority,
});

rankBy runs once per node; lower finite numbers order nodes that share a crossing-reduced sibling lane, so unrelated branches remain contiguous. The callback must not change graph topology. Parents are centered over their children with size-aware clearance. Use edge curvature for routed hierarchy views.

Capability tracker: FEATURE-PARITY.md. Release and security processes: POLICY.md, SECURITY.md.

Derived projections

og.projections.defineNode('risk', ({ degree, data }) =>
  (data as { base: number }).base + degree * 10);
og.projections.defineEdge('exposure', ({ sourceValue, targetValue, data }) =>
  (sourceValue<number>('risk') ?? 0)
  + (targetValue<number>('risk') ?? 0)
  + (data as { amount: number }).amount);
og.transformations.addFilter(({ value }) => (value<number>('risk') ?? 0) >= 90);
og.styles.addNodeRule(({ value }) => ({
  color: (value<number>('risk') ?? 0) >= 90 ? '#dc2626' : '#64748b',
}));

og.updateNode('account', { data: { base: 90 } });
og.projections.refresh(); // required after data or topology changes

Force layout options

og.layouts.force({
  iterations: 300,
  balance: 'adaptive', // bounded tuning from graph size and mean degree
  bodyMass: ({ degree }) => Math.max(1, degree),
  linkPull: ({ data }) => typeof data === 'object' && data !== null && 'pull' in data
    ? Number(data.pull)
    : 1,
  repulsion: 1200,     // many-body strength
  springLength: 30,    // edge rest length
  springK: 0.05,       // spring stiffness
  gravity: 0.02,       // pull toward origin
  theta: 0.9,          // Barnes-Hut opening angle
  velocityDecay: 0.6,  // friction
  maxVelocity: 60,     // per-tick displacement cap (stability)
  sync: false,         // true = run on main thread
});

Callbacks run once on the calling thread and transfer compact numeric fields to the worker. Weighted accelerated requests use the worker fallback so their physics never silently changes.

Architecture

src/
  core/Graph.ts         SoA typed-array store, id→index map, dirty flags
  render/Renderer.ts    WebGL2 instanced passes, shared RGBA32F position texture
  render/shaders.ts     SDF-circle nodes, screen-space edge quads (GLSL 300 es)
  render/Camera.ts      pan/zoom/fit, world↔screen transforms
  render/Labels.ts      Canvas2D overlay with zoom LOD
  layout/force.ts       Barnes-Hut (flat-array quadtree), velocity-capped
  layout/forceWorker.ts worker protocol: transferable frames
  layout/LayoutManager.ts
  analysis/              cancellable sync/worker graph insights
  timeline/Timeline.ts   dense intervals, filtering, playback, histogram
  geo/                    raster tiles, projection, GeoJSON vector layer
  spatial/Grid.ts       uniform hash grid: O(1) picking, viewport queries
  style/Styles.ts       rule-based styles compiled to typed-array writes
  interaction/           navigation, picking, lasso, and Forge editing
demo/                   Vite demo: configurable graph generator + FPS HUD
test/                   deterministic unit and Playwright regression evidence

Development

npm install
npm run dev        # demo at http://localhost:5199
npm test           # vitest suite
npm run typecheck
npm run build      # ES module + .d.ts into dist/
npm run build:site # Cloudflare-ready static site into site-dist/
npm run evidence:portable     # type/build/unit/browser push gate
npm run verify:consumer       # pack, isolated install, type/build/browser smoke
npm run evidence:release      # portable evidence followed by consumer verification
npm run evidence:performance  # named compatible performance gate
# Repeated physical candidate/reference commands and verdict policy:
# docs/performance/CERTIFICATION.md
npm run evidence:visual       # requires ignored licensed reference pixels

For Cloudflare Pages, use npm run build:site as the build command and site-dist as the output directory. The artifact includes the landing page, documentation, demo bench, example catalog, and every linked example without requiring a GitHub Actions workflow.

The repository-only consumer/investigation-desk/ is a focused cyber incident application and permanent release gate. Its verifier copies the app to a clean temporary directory and installs the generated tarball, never repository source. It checks public exports and worker assets while exercising search, selection, risk filters, timeline reduction, shortest-path analysis, atomic containment and undo, JSON downloads, responsive layout, and automated WCAG rules from the same package a customer receives.

Requirements

  • WebGL2 (universal in 2026 browsers). No fallback renderer — Ogjs fails fast with a clear error instead of a slow canvas path.
  • No runtime dependencies.

License

Commercial. Ogjs is proprietary software — see LICENSE.md. Evaluation use is permitted; production use requires a commercial license. Contact the maintainer for licensing terms.