How the React Dashboard Integrates with the Knowledge Graph Using React Flow

The React dashboard integrates with the knowledge graph by validating and loading a JSON payload into a Zustand store, computing force-directed layouts via D3, and rendering the positioned nodes and edges through React Flow components.

The Understand-Anything dashboard transforms static knowledge graph output from the /understand-knowledge pipeline into an interactive, explorable visualization. By combining a global state management layer with React Flow's node-edge diagram capabilities, the application delivers a fluid user experience for navigating complex knowledge relationships.

Architecture Overview

The integration relies on three core architectural layers that bridge raw data and interactive visualization.

Dashboard Store (useDashboardStore in store.ts) serves as the single source of truth, housing the raw KnowledgeGraph object, selection state, and derived lookup indexes. It manages the SearchEngine for fuzzy lookups and maintains fast access maps like nodesById and nodeIdToLayerId.

Force-Directed Layout Engine (applyForceLayout in utils/layout.ts) computes stable (x, y) coordinates for every node. The engine runs D3 force simulations with configurable link distances, charge strengths, and centering forces to produce deterministic layouts based on graph topology.

React Flow View (KnowledgeGraphView.tsx) transforms positioned graph data into React Flow compatible nodes and edges. This component handles the mapping of custom data properties, applies edge style presets, and manages the interactive canvas including zoom controls, background grids, and event handlers.

Data Flow from JSON to Interactive Diagram

The integration follows a six-stage pipeline that converts static JSON into a responsive visualization.

1. Loading and Validating the Graph

When the dashboard initializes in App.tsx, it fetches the knowledge graph JSON and validates it against the core schema. The validateGraph function from @understand-anything/core/schema ensures type safety before the data enters the store.

// App.tsx – load & validate graph
fetch(dataUrl("knowledge-graph.json", accessToken))
  .then(r => r.json())
  .then((data: unknown) => {
    const result = validateGraph(data);
    if (result.success && result.data) {
      setGraph(result.data);               // ← store receives the graph
    }
  });

2. Indexing with the Dashboard Store

The setGraph method in store.ts initializes the search infrastructure and builds fast lookup indexes. It instantiates a SearchEngine for fuzzy node lookup and creates bidirectional mapping tables for layer relationships.

// store.ts – setGraph implementation
const searchEngine = new SearchEngine(graph.nodes);
const { nodesById, nodeIdToLayerId, nodeIdToLayerIds } = buildGraphIndexes(graph);
set({ graph, nodesById, nodeIdToLayerId, nodeIdToLayerIds, searchEngine });

3. Computing Force-Directed Layouts

Inside KnowledgeGraphView.tsx, the computeLayout function processes filtered graph data through applyForceLayout. The layout engine runs a deterministic number of simulation ticks based on node count to ensure stable positioning.

// KnowledgeGraphView.tsx – layout computation
const { positionMap, edgeCounts } = useMemo(() => {
  if (!filteredGraph) return { positionMap: new Map(), edgeCounts: new Map() };
  return computeLayout(filteredGraph);        // ← force-directed layout
}, [filteredGraph]);

The underlying D3 simulation in utils/layout.ts configures link forces, many-body charge forces, and centering forces. The tick count scales with graph size: Math.min(300, Math.max(100, nodes.length)).

// utils/layout.ts – force simulation setup
const sim = forceSimulation<ForceNode>(simNodes)
  .force("link", forceLink(...).distance(linkDistance))
  .force("charge", forceManyBody().strength(chargeStrength))
  .force("center", forceCenter(0, 0).strength(0.03));
const ticks = Math.min(300, Math.max(100, nodes.length));
sim.tick(ticks);

4. Mapping to React Flow Components

With coordinates calculated, the component constructs React Flow Node and Edge objects. Nodes receive enriched data properties including selection state, search highlighting flags, and incoming edge counts. Edges map to style presets based on relationship type.

// KnowledgeGraphView.tsx – node construction
const rfNodes: Node[] = filteredGraph.nodes.map(node => ({
  id: node.id,
  type: "custom",
  position: positionMap.get(node.id) ?? { x: 0, y: 0 },
  data: {
    label: node.name,
    nodeType: node.type,
    isSelected,
    isHighlighted,
    onNodeClick,
    incomingCount: edgeCounts.get(node.id) ?? 0,
  },
}));

5. Rendering the Interactive Canvas

The KnowledgeGraphView renders the ReactFlow component with strict zoom boundaries and registered custom node types. The nodeTypes map directs React Flow to render each node using the CustomNode component.

<ReactFlow
  nodes={nodes}
  edges={edges}
  nodeTypes={nodeTypes}
  fitView
  minZoom={0.05}
  maxZoom={2}
>
  <Background variant={BackgroundVariant.Dots} />
  <Controls />
  <MiniMap />
</ReactFlow>

6. Handling User Interactions

User actions propagate through the Zustand store. Methods like selectNode and setFocusNode mutate selection state, triggering memoized recalculations of node and edge arrays. This architecture allows visual updates—such as highlighting or opacity changes—without recomputing expensive force-directed layouts.

Practical Implementation Examples

Loading a Knowledge Graph Programmatically

import { useEffect } from "react";
import { useDashboardStore } from "./store";
import KnowledgeGraphView from "./components/KnowledgeGraphView";

export default function Dashboard({ accessToken }: { accessToken: string }) {
  const setGraph = useDashboardStore(s => s.setGraph);

  useEffect(() => {
    fetch(`/knowledge-graph.json?token=${accessToken}`)
      .then(r => r.json())
      .then(data => setGraph(data));
  }, [accessToken, setGraph]);

  return (
    <div className="h-full w-full">
      <KnowledgeGraphView />
    </div>
  );
}

Customizing Edge Visual Styles

Edge appearance varies by relationship type through the EDGE_STYLES record. You can extend this mapping to support new knowledge graph relationships.

// KnowledgeGraphView.tsx – extend EDGE_STYLES
const EDGE_STYLES: Record<string, React.CSSProperties> = {
  "related": { stroke: "var(--color-border-medium)", strokeWidth: 0.5, opacity: 0.12 },
  "cites":   { stroke: "var(--color-node-source)", strokeWidth: 1.5, strokeDasharray: "6 3" },
  "inspired_by": { stroke: "#a0c4ff", strokeWidth: 1, opacity: 0.7 },
};

Highlighting Nodes via Store Actions

import { useDashboardStore } from "./store";

function highlightNode(nodeId: string) {
  const selectNode = useDashboardStore.getState().selectNode;
  selectNode(nodeId);          // updates selectedNodeId → UI re-renders
}

Summary

  • Zustand Store (store.ts) manages the raw knowledge graph, search indexes, and UI selection state, providing a centralized data layer for the React Flow visualization.
  • Force-Directed Layout (utils/layout.ts) calculates stable node positions using D3 force simulation with topology-aware tick counts.
  • React Flow Integration (KnowledgeGraphView.tsx) converts positioned graph data into interactive nodes and edges, handling rendering, custom styling, and user interactions.
  • Performance Optimization relies on memoization of layout calculations and selective store updates, ensuring the UI remains responsive during graph exploration.
  • Schema Validation occurs at load time via validateGraph, ensuring only valid knowledge graph structures enter the visualization pipeline.

Frequently Asked Questions

How does the dashboard load the initial knowledge graph data?

The dashboard fetches a JSON representation from knowledge-graph.json during the boot sequence in App.tsx. The data passes through validateGraph from @understand-anything/core/schema to ensure type safety before being committed to the useDashboardStore via setGraph.

What algorithm determines the positioning of nodes in the visualization?

The system uses a force-directed layout algorithm implemented in utils/layout.ts. It employs D3's forceSimulation with link distance forces, many-body charge forces, and centering forces. The simulation runs for a calculated number of ticks—between 100 and 300 depending on node count—to produce stable, visually coherent arrangements.

How does the dashboard maintain performance when filtering large graphs?

The implementation uses memoized layout computation via useMemo in KnowledgeGraphView.tsx. The positionMap and edgeCounts only recalculate when the filteredGraph reference changes. User interactions like selection or search updates mutate only the UI state flags (e.g., isHighlighted), avoiding expensive layout recomputation.

Can developers customize the appearance of nodes and edges?

Yes. Nodes render through the CustomNode component mapped via the nodeTypes prop in React Flow. Edges support relationship-specific styling through the EDGE_STYLES record in KnowledgeGraphView.tsx, allowing distinct colors, stroke widths, and dash patterns for different knowledge graph relationship types.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →