TypeScript + WebGPU

Graphs with depth.

BubbleGraph is a framework-agnostic TypeScript library for interactive, force-directed bubble graphs rendered with WebGPU.

One focused library.

Bring your own data and interface. BubbleGraph owns rendering, layout, animation, labels, interaction, image export, and cleanup.

01

GPU-native rendering

WebGPU-batched soap-bubble nodes and instanced edges keep drawing work compact.

02

Hybrid force layout

GPU uniform-grid repulsion with a CPU fallback, plus collision constraints, edge springs, shuffle, and animated entrances.

03

Readable at scale

Perspective-aware, raster-cached multiline labels use level of detail and a bounded budget.

04

Graph interaction

Pan, zoom, selection, hover, activation, hit testing, fit-to-view, and contextual removal.

05

Framework neutral

Use it from plain TypeScript or wrap it in React, Vue, Svelte, or your own application shell.

06

Export and diagnostics

Export the whole graph as a high-resolution PNG and observe live FPS, frame time, node, and edge statistics.

Coming soon

Small API.
Full graph UI.

This preview shows the API currently used by the examples. Distribution and installation instructions will be added when the library is released.

01

Create the graph

Supply a positioned container and optional callbacks for selection, hover, activation, removal, rendering, and performance statistics.

02

Add your data

Each datum needs a stable ID, label, numeric value, and any host-specific payload.

03

Connect and control

Add edges, update node state, fit or shuffle the view, and export the finished graph as a PNG.

04

Clean up

Call destroy() when the host view unmounts.

import { BubbleGraph } from "bubblegraph";

const graph = await BubbleGraph.create({
  container: document.querySelector<HTMLElement>("#graph")!,
  onSelect: (index, node) => console.log(node),
});

const root = graph.add({
  id: "root", label: "Root item",
  value: 120, data: { url: "/root" },
});

const child = graph.add({
  id: "child", label: "Related item",
  value: 20, data: { url: "/child" },
}, root);

graph.connect(root, child);
graph.fit();

Requires a browser with WebGPU · HTTPS or localhost