Skip to main content
CodeGraph is built on a three-layer architecture that separates concerns and enables extensibility through plugins and integrations.

The Three Layers

Analyzer

Parses source code and extracts structure (classes, methods, dependencies)

Graph Database

Stores the code structure as nodes and relationships

Visualization

Renders the graph as an interactive 3D experience
Currently uses Roslyn for C#, with potential for other parsers (tree-sitter) in the future.

Hexagonal Architecture

CodeGraph follows hexagonal architecture (ports and adapters). The core business logic sits in the center and knows nothing about the outside world.
Hexagonal Architecture

The Core

The core contains pure business logic—no frameworks, no databases, no HTTP. It defines ports (interfaces) for everything it needs.

Driving Adapters (Input)

Driving adapters call into the core. They handle incoming requests:

CLI

.NET ConsoleCommand-line interface for analysis

REST API

ASP.NET CoreHTTP endpoints for the frontend

React Frontend

React + Three.js3D visualization and interaction

Driven Adapters (Output)

Driven adapters are called by the core through ports:

Roslyn Analyzer

Microsoft.CodeAnalysisImplements IStructuralAnalyzer

Neo4j Storage

Neo4j.DriverImplements IGraphStorage

GraphPU Layout

Rust + Metal/VulkanImplements ILayoutCompute

Ports

The core defines interfaces (ports) that adapters implement. This allows swapping implementations without changing business logic.
Analyzes source code and extracts structure.Implementations: Roslyn (C#), Tree-sitter (future)
public interface IStructuralAnalyzer
{
    Task<AnalysisResult> AnalyzeAsync(string path, CancellationToken ct);
}
Persists and queries the code graph.Implementations: Neo4j, Memgraph, In-Memory
public interface IGraphStorage
{
    Task<IEnumerable<GraphNode>> GetNodesAsync(CancellationToken ct);
    Task<IEnumerable<GraphEdge>> GetEdgesAsync(CancellationToken ct);
    Task SaveAnalysisResultAsync(AnalysisResult result, CancellationToken ct);
}
Computes node positions using force-directed algorithms.Implementations: GraphPU (Metal), GraphPU (Vulkan), CPU Fallback
public interface ILayoutCompute
{
    Task<LayoutResult> ComputeLayoutAsync(
        IEnumerable<GraphNode> nodes,
        IEnumerable<GraphEdge> edges,
        CancellationToken ct);
}

Data Flow

1

User triggers analysis

Through CLI command or React UI button click
2

Driving adapter calls core

The REST API receives the request and calls core business logic
3

Core orchestrates through ports

Core calls IStructuralAnalyzer.AnalyzeAsync() — doesn’t know it’s Roslyn
4

Driven adapter does the work

Roslyn adapter parses the code and returns nodes/edges
5

Core stores results

Core calls IGraphStorage.SaveAsync() — doesn’t know it’s Neo4j
6

Response flows back

Results return through the driving adapter to the user

Why This Separation?

Each layer and adapter can evolve independently:
ComponentCan be replaced with
RoslynTree-sitter for other languages
Neo4jMemgraph, PostgreSQL, or in-memory
GraphPUCPU-based layout, different algorithms
React FrontendDesktop app, VR client, VS Code extension

Plugin System

Plugins are just adapters that implement the same ports:
public interface IOverlayPlugin
{
    string Id { get; }
    string Name { get; }
    Task ApplyAsync(IGraphStorage storage, CancellationToken ct);
    Task RemoveAsync(IGraphStorage storage, CancellationToken ct);
}
Community plugins are first-class citizens—they can do anything built-in components can do.
Plugin TypeExamples
Overlay pluginsGit activity, test coverage, complexity metrics
Analyzer pluginsTypeScript parser, Python parser
Export pluginsJSON, GraphML, DOT format

Benefits

Testability

Mock any external dependency. Test business logic in isolation without databases or APIs.

Swappability

Replace any component without touching core. Switch databases, add languages, change providers.

What’s Next?