Entity Graph
Interactive relationship graph visualization using @xyflow/react and D3 force-directed layout, with filtering, search, focus mode, and embeddable block support.
Entity Graph
The Entity Graph renders all entity records and their relationships as an interactive node-link diagram. Nodes represent entities (colored by type), edges represent relations, and the layout is computed via a D3 force-directed simulation. The graph supports filtering by type and relation, searching by title, focusing on a single entity's neighborhood, and embedding as a block in entity detail views.
Overview
The graph is accessible at /graph as a full-page experience and can be embedded in entity detail pages via the entity-graph block type. The module lives in features/graph/ and uses @xyflow/react for pan/zoom canvas rendering with custom node components. The layout engine uses d3-force for physics-based positioning, running synchronously to convergence before rendering.
Key Concepts
GraphNode -- A node in the graph: id, title, type (human-readable type name), typeSlug, and optional icon.
GraphEdge -- A directed edge: id, source (entity ID), target (entity ID), and label (relationship type string).
GraphData -- The container type holding arrays of GraphNode and GraphEdge.
GraphConfig -- Controls what the graph shows and how:
focusEntityId-- center on this entity and highlight its neighborhoodtypeFilter-- array of entity type slugs to includerelationFilter-- array of relationship types to includesearchQuery-- highlights matching nodeslimit-- max nodes to display (default 50, API max 1000)showToolbar-- whether to show filter/search controlsshowLegend-- whether to show the type color legendcompact-- smaller nodes for sidebar/block useheight-- CSS height override
SimNode / SimLink -- Extended types used by the D3 force simulation, adding position (x, y), velocity, and connectionCount to GraphNode.
NodeSummary -- Lightweight identity passed through selection callbacks: title, typeSlug, typeName.
How It Works
Data Fetching
The GET /api/graph route supports two modes:
-
Neighborhood mode (
?entityId=...) -- fetches the specified entity and all entities one hop away viaentity_relations. Returns a compact subgraph. -
Full graph mode (optional
?types=...&limit=...) -- fetches up tolimitentities (default 500, max 1000), optionally filtered by comma-separated type slugs. Relations are fetched with a limit of3xthe entity limit.
Both modes are tenant-scoped and require authentication.
Force-Directed Layout
The computeForceLayout() function in features/graph/lib/force-layout.ts runs a D3 force simulation synchronously:
- Charge force -- repulsion between nodes (default -300 strength)
- Link force -- attraction along edges (default 120px distance)
- Center force -- pulls the graph toward the viewport center
- Collision force -- prevents overlap, with radius scaled by connection count
- Centering forces -- gentle X/Y forces prevent drift
The simulation runs for 300 ticks by default, producing settled positions without animation. Node radius scales with connection count: max(20, 20 + sqrt(connections) * 6).
Rendering Pipeline
computeForceLayout()produces positionedSimNode[]andSimLink[]buildFlowNodes()andbuildFlowEdges()convert these to@xyflow/reactNode[]andEdge[], applying interaction state (hover highlighting, search matches, focus dimming, selection)GraphCanvasrenders viaReactFlowwith customGraphNodecomponents- Interaction: hovering a node highlights it and its neighbors, dims everything else. Clicking navigates to the entity detail page.
Graph Utilities
The features/graph/lib/graph-utils.ts file provides pure functions:
buildConnectionCounts(nodes, edges)-- counts connections per nodebuildAdjacency(edges)-- builds an undirected adjacency mapaggregateNodeTypes(nodes)-- groups nodes by type with counts, sorted descendingfilterGraphData(nodes, edges, typeFilter?, relationFilter?)-- applies type and relation filterscapGraphData(data, focusEntityId?, maxNodes?)-- caps node count for performance, keeping the focus entity and most-connected nodes
Graph Variants
| Component | Use Case |
|---|---|
FullGraph | Full-page /graph experience with toolbar, legend, and detail panel |
GraphCanvas | Reusable canvas component with pan/zoom |
MiniGraph | Compact version for sidebar or embedded use |
EntityGraphBlockView | Block renderer for embedding in entity detail views |
API Reference
API Route
| Endpoint | Method | Parameters |
|---|---|---|
/api/graph | GET | entityId? (neighborhood mode), types? (comma-separated slugs), limit? (1-1000) |
Core Types
| Type | Location | Purpose |
|---|---|---|
GraphNode | features/graph/types.ts | Node data |
GraphEdge | features/graph/types.ts | Edge data |
GraphConfig | features/graph/types.ts | Display configuration |
GraphData | features/graph/types.ts | Container for nodes + edges |
SimNode, SimLink | features/graph/types.ts | Force simulation types |
Key Functions
| Function | Location | Purpose |
|---|---|---|
computeForceLayout(nodes, edges, options) | features/graph/lib/force-layout.ts | D3 force simulation |
nodeRadius(connectionCount) | Same | Compute node size |
buildFlowNodes(ctx) | features/graph/lib/build-flow-elements.ts | Convert to xyflow nodes |
buildFlowEdges(ctx) | Same | Convert to xyflow edges |
filterGraphData(...) | features/graph/lib/graph-utils.ts | Apply type/relation filters |
capGraphData(data, focusId?, max?) | Same | Cap nodes for performance |
getTypeColor(typeSlug) | features/graph/lib/colors.ts | Consistent color per type |
Barrel Exports
The features/graph/index.ts barrel exports: FullGraph, GraphCanvas, MiniGraph, EntityGraphBlockView, useGraphData, getTypeColor, getTypeBgColor, and all core types.
For Agents
Agents interact with graph data indirectly through entity and relation tools:
searchEntities-- find nodesgetEntity-- get entity detailscreateRelation-- add edges to the graphlistEntityTypes-- understand the type landscape
The graph visualization is a read-only rendering of the entity-relation data that agents create and modify through these tools.
Related Modules
- Entity System (
features/entities/) -- provides the data (entities + relations) - Block System (
features/blocks/) --entity-graphblock type embeds the graph in views - Views (
features/views/) -- graph blocks can be included in detail and workspace views