Graph Visualizer

JSON format

The visualizer reads a single JSON document with a top-level nodes array. Each node carries its outgoing edges as a list of target node ids. The whole file is read in the browser — nothing is uploaded.

Schema

{  "nodes": [
    {      "id":    string | number,         "label": string,                  "type":  string,                  "edges": Edge[],                  "meta":  any                    }, ...
  ]
}
type Edge =
  | string | number                              | { "nodeId": string | number,
      "edgeType": string }                       

Fields

id — required
Unique identifier for the node. May be a string or number; numbers are coerced to strings internally. Duplicate ids cause a parse error.
label — optional
Display text shown in the info panel when the node is selected. Defaults to id.
type — optional
Free-form kind classifier — for example "package", "file", "class". Distinct values are interned the same way edge types are, and the selected-node panel surfaces the type alongside id and degree counts.
edges — optional
An array of outgoing edges. Each entry is either a bare target id (string or number) or an object { nodeId, edgeType } where nodeId is the target and edgeType is a string label classifying the relationship ("calls", "depends-on", etc.). Both forms can be mixed in the same array. Edges referencing unknown ids are dropped with a console warning; duplicate (from, to) pairs are collapsed (first edge type wins); self-loops are dropped.
meta — optional
Any user-defined object. Rendered as a key/value list in the selected node panel. Top-level keys with string/number/boolean values render as text; nested objects are serialized as JSON.

Examples

Minimal

{
  "nodes": [
    { "id": "a", "edges": ["b", "c"] },
    { "id": "b", "edges": ["c"] },
    { "id": "c" }
  ]
}

With labels

{
  "nodes": [
    { "id": "auth", "label": "Authentication service" },
    { "id": "billing", "label": "Billing service", "edges": ["auth"] },
    { "id": "reports", "label": "Reports", "edges": ["auth", "billing"] }
  ]
}

With meta

{
  "nodes": [
    {
      "id": "src/index.ts",
      "label": "index.ts",
      "edges": ["src/util.ts", "src/api.ts"],
      "meta": { "lines": 142, "owner": "platform" }
    },
    {
      "id": "src/util.ts",
      "label": "util.ts",
      "meta": { "lines": 38 }
    },
    {
      "id": "src/api.ts",
      "label": "api.ts",
      "edges": ["src/util.ts"],
      "meta": { "lines": 207 }
    }
  ]
}

With typed edges

{
  "nodes": [
    {
      "id": "AuthService",
      "edges": [
        { "nodeId": "User",       "edgeType": "depends-on" },
        { "nodeId": "TokenStore", "edgeType": "depends-on" },
        { "nodeId": "Logger",     "edgeType": "calls" }
      ]
    },
    { "id": "User" },
    { "id": "TokenStore", "edges": ["Logger"] },
    { "id": "Logger" }
  ]
}

With node types

{
  "nodes": [
    {
      "id": "@acme/auth",
      "type": "package",
      "edges": ["@acme/auth/auth-service.ts", "@acme/auth/session.ts"]
    },
    {
      "id": "@acme/auth/auth-service.ts",
      "type": "file",
      "label": "@acme/auth/auth-service.ts",
      "edges": [
        { "nodeId": "@acme/auth/session.ts", "edgeType": "imports" },
        { "nodeId": "@acme/auth/types.ts",   "edgeType": "type-imports" }
      ]
    },
    { "id": "@acme/auth/session.ts", "type": "file" },
    { "id": "@acme/auth/types.ts",   "type": "file" }
  ]
}

Notes

  • The graph is treated as directededges on node A pointing at node B means "A → B".
  • Communities are computed automatically with Louvain modularity clustering.
  • Initial positions are computed with a d3-force simulation. Layout runs in a Web Worker and emits ~12 batches before settling.
  • The renderer is WebGL2-instanced; 50k+ nodes are practical on modern hardware.

Back to the dropzone