Skip to content

Instantly share code, notes, and snippets.

@gwpl
Last active February 11, 2026 17:32
Show Gist options
  • Select an option

  • Save gwpl/bfce3a04344d8ad493fac3936a85b672 to your computer and use it in GitHub Desktop.

Select an option

Save gwpl/bfce3a04344d8ad493fac3936a85b672 to your computer and use it in GitHub Desktop.
Graph Rendering and UI of EdgeQuake Analyzed (Sigma.js , implementation references etc)

Sigma.js in EdgeQuake: Graph Visualization Architecture

Date: February 2026 Repository: EdgeQuake Visualization Library: Sigma.js | GitHub


Executive Summary

This document analyzes how EdgeQuake, a high-performance Graph-RAG framework written in Rust, leverages Sigma.js for interactive knowledge graph visualization. This architecture pattern demonstrates how Rust-based backend systems can seamlessly integrate with modern JavaScript visualization libraries to create compelling user experiences.

Key Insight: This pattern is highly applicable to other Rust-based graph databases like Oxigraph (SPARQL RDF database), which currently lacks a sophisticated web UI for graph visualization.


1. Why Sigma.js? The Technology Choice

What is Sigma.js?

Sigma.js is a WebGL-powered JavaScript library specifically designed for rendering and interacting with large-scale network graphs (thousands of nodes and edges) directly in the browser.

Core Capabilities:

  • Performance: "WebGL-accelerated rendering enables smooth 60fps animations even with 1000+ nodes"
  • Scalability: Handles large graphs that would overwhelm Canvas or SVG-based solutions (like D3.js)
  • Architecture: Works in symbiosis with Graphology, which handles graph data structures and algorithms
  • Ecosystem: Rich plugin ecosystem including layouts, community detection, and interactive controls

EdgeQuake's Stack: Rust Backend + React Frontend

Backend (Rust):

  • Rust-based Graph-RAG engine with PostgreSQL AGE (graph storage) + pgvector (embeddings)
  • Entity extraction, relationship mapping, and knowledge graph construction
  • REST API (Axum) with SSE streaming for real-time responses

Frontend (React 19 + TypeScript):

  • Next.js 16.1.0 with App Router
  • Tailwind CSS 4.1.18 + shadcn/ui components
  • Sigma.js 3.0.2 for graph rendering
  • Graphology for graph data manipulation and layout algorithms

2. The Rendering Pipeline: From Rust to WebGL

Architecture Overview

┌──────────────────────────────────────────────────┐
│ Rust Backend (EdgeQuake Core)                   │
│ ┌────────────────────────────────────────────┐   │
│ │ Knowledge Graph (PostgreSQL AGE)           │   │
│ │ * Entities (nodes): people, orgs, concepts │   │
│ │ * Relationships (edges): connects entities │   │
│ └────────────────┬───────────────────────────┘   │
│                  │                               │
│                  │ REST API /api/v1/graph        │
└──────────────────┼───────────────────────────────┘
                   │
                   ▼
           JSON (nodes, edges, metadata)
                   │
                   ▼
┌──────────────────────────────────────────────────┐
│ React Frontend (graph-renderer.tsx)              │
│ ┌────────────────────────────────────────────┐   │
│ │ 1. Data Transformation                     │   │
│ │    EdgeQuake JSON → Graphology Graph       │   │
│ └────────────────┬───────────────────────────┘   │
│                  │                               │
│                  ▼                               │
│ ┌────────────────────────────────────────────┐   │
│ │ 2. Layout Computation (Graphology)         │   │
│ │    * ForceAtlas2 (force-directed, physics) │   │
│ │    * Force Layout (spring-based)           │   │
│ │    * Circular Layout                       │   │
│ └────────────────┬───────────────────────────┘   │
│                  │                               │
│                  ▼                               │
│ ┌────────────────────────────────────────────┐   │
│ │ 3. Sigma.js WebGL Rendering                │   │
│ │    * Node rendering (circles, custom)      │   │
│ │    * Edge rendering (lines, curves)        │   │
│ │    * Camera controls (zoom, pan)           │   │
│ │    * Event handlers (click, hover, drag)   │   │
│ └────────────────┬───────────────────────────┘   │
│                  │                               │
│                  ▼                               │
│ ┌────────────────────────────────────────────┐   │
│ │ 4. User Interaction Layer                  │   │
│ │    * Node selection and highlighting       │   │
│ │    * Neighborhood exploration              │   │
│ │    * Search and filtering                  │   │
│ │    * Minimap navigation                    │   │
│ └────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────┘

Code Flow (from DeepWiki Analysis)

Step 1: Graph Renderer Entry Point (graph-renderer.tsx:85)

export function GraphRenderer({ nodes, edges, onNodeClick, onNodeHover, onNodeRightClick }: GraphRendererProps) {
  // Main component orchestrating graph visualization
}

Step 2: Graphology Instance Creation (graph-renderer.tsx:277)

const graph = new Graph();
// Graph data structure from Graphology library

Step 3: Sigma.js WebGL Renderer Initialization (graph-renderer.tsx:505)

const sigma = new Sigma(graph, containerRef.current, {
  // Instantiates WebGL rendering engine
});

Step 4: Node Interaction Event Handler (graph-renderer.tsx:546)

sigma.on('clickNode', (event) => {
  // Interactive node selection and callbacks
});

3. Key Features Implemented in EdgeQuake

3.1 Layout Algorithms (Graphology Integration)

EdgeQuake uses multiple layout algorithms through Graphology:

  1. ForceAtlas2 (Primary)

    • Physics-based force-directed layout
    • Nodes repel each other, edges act as springs
    • Self-organizes into clusters revealing communities
    • Ideal for knowledge graphs where relationships define structure
  2. Force Layout

    • Spring-based alternative to ForceAtlas2
    • Faster computation, good for real-time updates
  3. Circular Layout

    • Arranges nodes in a circle
    • Useful for comparing graph structures or small graphs

3.2 Interactive Features

From the Implementation:

  • Node Click: Opens detailed entity information
  • Node Hover: Highlights node and its immediate neighbors
  • Node Right-Click: Context menu for additional actions
  • Drag & Drop: Repositioning nodes manually
  • Zoom & Pan: Camera controls for exploring large graphs
  • Minimap: Overview navigation for large knowledge graphs
  • Search: Find specific entities by name/type

3.3 Real-Time Streaming Integration

EdgeQuake's REST API provides SSE (Server-Sent Events) for real-time graph updates:

  • As new documents are ingested, new entities/relationships appear in the graph
  • Live progress tracking during document processing
  • Token-by-token LLM response generation displayed alongside graph exploration

4. Performance Characteristics

Why WebGL Matters

Aspect Sigma.js (WebGL) D3.js (SVG/Canvas)
Node Capacity 10,000+ nodes ~1,000 nodes (before lag)
Rendering Speed 60 FPS animations 15-30 FPS with large graphs
Layout Animation Smooth physics Stuttering on large datasets
Memory Efficiency GPU-accelerated CPU-bound, higher memory
Customization Moderate (WebGL shaders) Highly flexible (SVG/Canvas)

EdgeQuake's Benchmark Results:

  • Query latency (hybrid mode): < 200ms
  • Concurrent users: 1000+
  • Graph rendering: Real-time even with complex knowledge graphs (100+ entities, 200+ relationships)

Trade-offs

When Sigma.js Excels:

  • Large graphs (500+ nodes)
  • Real-time updates and streaming
  • Performance-critical applications

When D3.js is Better:

  • Small graphs (< 500 nodes)
  • Highly customized visualizations (e.g., hierarchical trees, specialized node shapes)
  • SVG-based interactivity (easier DOM manipulation)

5. Integration Pattern: Rust + JavaScript

API Contract

Rust Backend Endpoint: GET /api/v1/graph

{
  "nodes": [
    {
      "id": "entity-123",
      "label": "Knowledge Graph",
      "type": "CONCEPT",
      "description": "Structured representation of entities and relationships",
      "x": 0.5,
      "y": 0.3,
      "size": 10,
      "color": "#3b82f6"
    }
  ],
  "edges": [
    {
      "source": "entity-123",
      "target": "entity-456",
      "type": "ENABLES",
      "keywords": ["retrieval", "reasoning"],
      "weight": 0.85
    }
  ],
  "communities": [
    {
      "id": "community-1",
      "entities": ["entity-123", "entity-456"],
      "title": "Core RAG Concepts"
    }
  ]
}

React Frontend Transformation:

// Convert EdgeQuake API response to Graphology format
const graph = new Graph();

apiResponse.nodes.forEach(node => {
  graph.addNode(node.id, {
    label: node.label,
    x: node.x,
    y: node.y,
    size: node.size,
    color: node.color,
    type: node.type
  });
});

apiResponse.edges.forEach(edge => {
  graph.addEdge(edge.source, edge.target, {
    type: edge.type,
    weight: edge.weight
  });
});

// Pass to Sigma.js for rendering
const sigmaInstance = new Sigma(graph, container);

6. Lessons for Oxigraph and SPARQL RDF Applications

The Opportunity

Oxigraph is a SPARQL-compliant graph database written in Rust (similar architecture to EdgeQuake's backend). However, it lacks a sophisticated web UI for graph exploration.

Applying EdgeQuake's Pattern

Proposed Architecture for Oxigraph + Sigma.js:

┌─────────────────────────────────────────────────┐
│ Oxigraph (Rust SPARQL Database)                 │
│ ┌───────────────────────────────────────────┐   │
│ │ RDF Triples (RocksDB Storage)             │   │
│ │ * Subject-Predicate-Object triples        │   │
│ │ * SPARQL 1.1 Query, Update, Federated     │   │
│ └────────────┬──────────────────────────────┘   │
│              │ REST API + SPARQL Protocol       │
└──────────────┼──────────────────────────────────┘
               │
               └─► SPARQL Query Results (JSON)
                              │
                              ▼
┌─────────────────────────────────────────────────┐
│ React Frontend (oxigraph-ui)                    │
│ ┌───────────────────────────────────────────┐   │
│ │ 1. SPARQL Query Interface                 │   │
│ │    * Query editor with syntax highlight   │   │
│ │    * Example queries (CONSTRUCT graphs)   │   │
│ └────────────┬──────────────────────────────┘   │
│              │                                   │
│              ▼                                   │
│ ┌───────────────────────────────────────────┐   │
│ │ 2. RDF to Graph Transformation            │   │
│ │    * SPARQL CONSTRUCT → Nodes & Edges     │   │
│ │    * RDF literals → Node labels           │   │
│ │    * RDF properties → Edge types          │   │
│ └────────────┬──────────────────────────────┘   │
│              │                                   │
│              ▼                                   │
│ ┌───────────────────────────────────────────┐   │
│ │ 3. Sigma.js Graph Visualization           │   │
│ │    * Same EdgeQuake pattern: Graphology   │   │
│ │    * Layout: ForceAtlas2 for RDF graphs   │   │
│ │    * Interactive query exploration        │   │
│ └───────────────────────────────────────────┘   │
└─────────────────────────────────────────────────┘

Implementation Steps

  1. Create SPARQL CONSTRUCT Queries

    • Query triples and return them as named graphs
    • Example: Extract all entities of type Person and their relationships
    PREFIX ex: <http://example.org/>
    CONSTRUCT {
      ?subject ?predicate ?object .
    }
    WHERE {
      ?subject a ex:Person ;
               ?predicate ?object .
    }
  2. Transform RDF Results to Graph Format

    // Convert SPARQL JSON results to Sigma.js format
    const nodes = new Set();
    const edges = [];
    
    results.forEach(binding => {
      // subject → node
      nodes.add({ id: binding.subject.value, label: extractLabel(binding.subject) });
      // object (if URI) → node
      if (binding.object.type === 'uri') {
        nodes.add({ id: binding.object.value, label: extractLabel(binding.object) });
        // predicate → edge
        edges.push({
          source: binding.subject.value,
          target: binding.object.value,
          type: extractPredicate(binding.predicate)
        });
      }
    });
  3. Deploy with Sigma.js

    • Reuse EdgeQuake's React component architecture
    • Apply same layout algorithms (ForceAtlas2)
    • Implement query builder UI for SPARQL construction

Advantages of This Approach

Aspect Benefit
Reusability EdgeQuake's component patterns directly transfer to RDF contexts
Performance Sigma.js handles complex SPARQL result sets efficiently
Standards Compliance SPARQL remains the query interface; visualization is additive
Knowledge Discovery Visual exploration of RDF ontologies reveals schema patterns
Reduced Development Time Leverage existing Rust + React integration patterns

7. Technical Deep Dive: Sigma.js Rendering Lifecycle

Rendering Process

  1. Graph Instantiation

    • Graphology creates in-memory graph structure
    • All nodes and edges loaded from API response
  2. Layout Computation

    • ForceAtlas2 algorithm iteratively positions nodes
    • Physics simulation: repulsive forces (nodes) + attractive forces (edges)
    • Converges toward stable, readable configuration
  3. WebGL Batch Rendering

    • "Sigma.js uses WebGL for GPU-accelerated rendering"
    • Nodes rendered as textured quads; edges as line segments
    • All rendered to canvas in single draw call per frame
  4. Camera & Viewport Management

    • Camera tracks user pan/zoom interactions
    • Viewport culling optimizes rendering (only visible nodes drawn)
    • Level-of-detail rendering (LOD) for distant nodes

Event Handling & Interactivity

// Core event pipeline
sigma.on('clickNode', (event) => {
  const { node } = event;
  // Fetch node details from backend
  // Update UI with entity information
  // Highlight node and neighborhood
});

sigma.on('hoverNode', (event) => {
  const { node } = event;
  // Highlight immediate neighbors
  // Show tooltip with node label
});

sigma.on('dragNode', (event) => {
  // Allow manual repositioning
  // Update node coordinates in local state
});

8. Conclusions & Recommendations

Why This Pattern Matters

"EdgeQuake demonstrates that modern visualization architectures require synergy between specialized backends and frontend libraries." Rust provides:

  • High-performance graph construction and storage
  • Efficient entity/relationship extraction from documents
  • Scalable streaming API infrastructure

JavaScript visualization libraries like Sigma.js provide:

  • Interactive exploration capabilities
  • GPU-accelerated rendering for large datasets
  • Responsive user experience

Best Practices for Similar Projects

  1. Separate Concerns: Keep graph computation (backend) distinct from visualization (frontend)
  2. Design API Contracts: Define clear JSON schemas for graph data exchange
  3. Optimize Data Transfer: Return only visible/relevant subgraphs to client
  4. Progressive Enhancement: Load additional details on user interaction
  5. Leverage Layout Libraries: Use battle-tested algorithms (ForceAtlas2) rather than custom implementations

Future Directions

  • Graph Streaming: WebSocket-based real-time graph updates
  • Collaborative Editing: Multi-user graph exploration with shared state
  • Advanced Filtering: Query-driven subgraph visualization
  • 3D Visualization: Extended Sigma.js with Three.js for spatial graphs
  • LLM Integration: AI-powered graph summarization and question-answering

References

https://deepwiki.com/search/what-is-edgequake-using-for-fr_d0822161-afaf-4291-a3ff-4122ff3578c8?mode=codemap

EdgeQuake Frontend Graph Visualization Architecture

This codemap traces EdgeQuake's frontend graph visualization architecture, showcasing the complete flow from data ingestion to interactive display. Key highlights include the Sigma.js WebGL rendering pipeline [1c], ForceAtlas2 layout algorithms [2a], comprehensive user interaction handling [3b], real-time minimap navigation [4b], and secondary Mermaid diagram integration [5c].

1. Graph Rendering Pipeline - From Data to WebGL Display

Core graph visualization flow using Sigma.js and Graphology for rendering knowledge graphs

1a. Graph Renderer Entry Point (graph-renderer.tsx:85)

Main component that orchestrates graph visualization with Sigma.js

export function GraphRenderer({ nodes, edges, onNodeClick, onNodeHover, onNodeRightClick }: GraphRendererProps)

1b. Graphology Instance Creation (graph-renderer.tsx:277)

Creates the underlying graph data structure using Graphology library

const graph = new Graph();

1c. Sigma.js WebGL Renderer Initialization (graph-renderer.tsx:505)

Instantiates Sigma.js for high-performance WebGL graph rendering

const sigma = new Sigma(graph, containerRef.current, {

1d. Node Interaction Event Handler (graph-renderer.tsx:546)

Registers click handlers for interactive node selection

sigma.on('clickNode', ({ node }) => { onNodeClick?.(node); });

2. Layout Algorithm Application - Force-Directed Graph Positioning

Graph layout computation using multiple algorithms for optimal node positioning

2a. ForceAtlas2 Layout Computation (graph-renderer.tsx:459)

Applies ForceAtlas2 algorithm for force-directed node positioning

forceAtlas2.assign(tempGraph, { iterations: 100, settings: { gravity: 1, scalingRatio: 2, strongGravityMode: true, barnesHutOptimize: tempGraph.order > 100, }, });

2b. Animated Layout Transitions (graph-renderer.tsx:778)

Smoothly animates nodes to new positions when layout changes

animateNodes(graph, newPositions, { duration: 300, easing: 'quadraticInOut' });

2c. Non-blocking Layout Updates (graph-renderer.tsx:211)

Uses RAF for performant incremental layout updates during streaming

rafIdRef.current = requestAnimationFrame(() => {

3. Interactive Graph Controls - User Interaction Flow

User interaction handling for zoom, pan, node selection, and context menus

3a. Main Graph Viewer Component (graph-viewer.tsx:68)

Orchestrates all graph visualization components and user interactions

export function GraphViewer() {

3b. Context Menu Trigger (graph-viewer.tsx:336)

Handles right-click events to open node context menus

const handleNodeRightClick = useCallback((nodeId: string, x: number, y: number) => { const node = allNodes.find((n) => n.id === nodeId); if (node) { openContextMenu(node, x, y); } }, [allNodes, openContextMenu]);

3c. Zoom Control Implementation (graph-viewer.tsx:314)

Provides animated zoom functionality for graph navigation

const handleZoomIn = () => { if (sigmaInstance) { const camera = sigmaInstance.getCamera(); camera.animatedZoom({ factor: 1.5 }); } };

3d. Graph Renderer Integration (graph-viewer.tsx:542)

Connects user interaction handlers to the core rendering component

<GraphRenderer nodes={filteredNodes} edges={filteredEdges} onNodeClick={selectNode} onNodeHover={hoverNode} onNodeRightClick={handleNodeRightClick} />

4. Minimap Navigation - Overview and Viewport Control

Real-time minimap generation and click-to-navigate functionality

4a. Minimap Component Definition (graph-minimap.tsx:23)

Creates a scaled-down overview of the entire graph

export function GraphMinimap({ width = 120, height = 100, position }: MinimapProps) {

4b. Canvas Rendering Logic (graph-minimap.tsx:68)

Renders graph nodes, edges, and viewport rectangle on HTML5 canvas

const drawMinimap = useCallback((sigma: Sigma) => {

4c. Click Navigation Handler (graph-minimap.tsx:202)

Animates main camera to clicked position on minimap

sigmaInstance.getCamera().animate({ x: graphX, y: graphY }, { duration: 300 });

4d. Real-time Updates Subscription (graph-minimap.tsx:237)

Redraws minimap when camera position changes

sigmaInstance.getCamera().on('updated', redraw);

5. Mermaid Diagram Integration - Secondary Visualization

Dynamic Mermaid diagram rendering for query responses with error handling

5a. Mermaid Component Definition (MermaidBlock.tsx:123)

Handles dynamic loading and rendering of Mermaid diagrams

export const MermaidBlock = memo(function MermaidBlock({ code, className, isStreaming = false, }: MermaidBlockProps) {

5b. Dynamic Mermaid Import (MermaidBlock.tsx:173)

Lazy-loads Mermaid library to reduce initial bundle size

const mermaid = await getMermaid();

5c. SVG Diagram Generation (MermaidBlock.tsx:187)

Converts Mermaid syntax to SVG for display

const { svg: renderedSvg } = await mermaid.render(`mermaid-${uniqueId}`, sanitized);

5d. SVG Rendering Output (MermaidBlock.tsx:305)

Injects rendered SVG into DOM for display

dangerouslySetInnerHTML={{ __html: svg }}

I'll help you find out what edgequake uses for its frontend, particularly for graph visualization and interaction.Based on my search of the EdgeQuake repository, here's what the project uses for its Frontend, especially for Graph visualization and interaction:

Frontend Framework & UI

Core Technology Stack:

  • Framework: Next.js 16.1.0 with App Router
  • UI Library: React 19.2.3
  • Language: TypeScript
  • Styling: Tailwind CSS 4.1.18 + shadcn/ui components

Graph Visualization & Interaction

Primary Libraries:

  1. Sigma.js 3.0.2 - The main graph rendering engine

    • WebGL-powered rendering for high performance
    • Handles 1000+ nodes efficiently
    • Provides smooth 60fps layout animations
  2. Graphology - Graph data structure and algorithms

    • Used for graph manipulation and traversal
    • Provides layout algorithms including:
      • ForceAtlas2 (force-directed layout)
      • Force Layout (spring-based)
      • Circular layout
      • Circle Pack layout
      • Noverlap (node overlap prevention)
      • Random layout

Key Graph Components:

/**
 * @module GraphRenderer
 * @description Sigma.js-powered graph renderer with layout algorithms.
 * Handles WebGL rendering, node/edge programs, and force-directed layouts.
 * 
 * @implements FEAT0601 - WebGL graph rendering with Sigma.js
 * @implements FEAT0603 - Force-directed layout algorithms (ForceAtlas2, circular, noverlap)
 * @implements FEAT0604 - Community detection and clustering visualization
 * @implements FEAT0605 - Theme-aware node and edge styling

Advanced Features:

  • Custom edge rendering with curved arrows (@sigma/edge-curve)
  • Custom node border programs (@sigma/node-border)
  • Community detection and clustering visualization
  • Interactive node selection, hovering, and focusing
  • Theme-aware styling (dark/light mode support)
  • Real-time graph filtering and search
  • Bookmarking system for graph views
  • Graph export capabilities (JSON format)

State Management

  • Zustand 5.0.9 - Used for graph state management (use-graph-store.ts)
  • Indexed data structures (Maps and Sets) for O(1) lookups of nodes and edges

Supporting Libraries

  • TanStack React Query 5.90.12 - Data fetching and caching
  • Lucide React - Icon system

View more results in GitHub

The architecture provides a sophisticated graph visualization experience with professional-grade performance for exploring knowledge graphs extracted from documents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment