Turn a CSV into an interactive network graph, entirely in the browser.
I built this for exploring blockchain transaction extractions — flat exports of transfers where the interesting part (which wallets keep showing up, where funds concentrate, what clusters exist) is invisible in a spreadsheet. It works on any CSV with entity columns, though: people and orgs, accounts and invoices, whatever.
Everything runs client-side. No backend, no upload, no storage. Refresh the page and the data is gone. This is deliberate — the data I use it on isn't the kind you paste into random web tools.
- Drop a CSV onto the page.
- Tick the columns that should become nodes (e.g.
from_address,to_address,tx_hash). - In the link mapper, drag between columns to define relationships, and click a column to give it a type or an alias (so wallets can display a label column instead of a raw address).
- Hit Build, or
Ctrl+Enter.
In the screenshot above the mapping is from_address → tx_hash → to_address, both edges labelled transfers, which gives a bipartite wallet/transaction graph. High-degree wallets are immediately obvious once you size nodes by degree.
Once built:
- Color nodes by type or by detected community (Louvain, implemented in
frontend/src/lib/communities.js— no dependency, fine with tens of thousands of nodes). - Filter via the legend, or raise the min-degree slider to strip out the periphery.
- Press
/to search for a node by name. - Click a node to see the CSV rows it came from, so you can check any pattern against the source data.
- Drag nodes to pin them, fullscreen the canvas, the usual.
cd frontend
npm install
npm run dev # http://localhost:3000npm run build produces a static site in frontend/build/ — it works served from anywhere, or opened straight off disk. npm test runs the vitest suite.
React 18 + Vite. React Flow for the link mapper, Papa Parse for CSV parsing.
The graph itself is a purpose-built engine in frontend/src/lib/graph/ — a WebGL2
instanced renderer (Canvas2D fallback), d3-force
running in a Web Worker, and a dirty-flag render loop, so a settled graph costs
nothing and tens of thousands of nodes stay interactive. See
frontend/src/lib/graph/GraphEngine.js
for the design notes.
