Skip to content

Architecture Overview

CapsaicinBunny edited this page Jun 20, 2026 · 1 revision

Architecture Overview

PolyGraph scans a codebase across 26 languages and renders an interactive node graph of its modules, types, functions, and the relationships between them. On top of the graph it offers impact analysis, a query language, package/workspace abstraction levels, architecture-rule enforcement and diffing (CLI), exports, and editor integration. It runs entirely locally — nothing is uploaded.

This page is the map. Each subsystem has its own deep-dive page, linked inline.

The pipeline

folder
  └─▶ Bun sidecar (server-side fs read)         sidecar/server.ts   →  POST /scan · /analyze · GET /health
        └─▶ language kernel                      lib/kernel/         →  buckets files by extension
              └─▶ providers (run concurrently)   lib/analyzer/ + analyzer-core/ (tree-sitter packs)
                    └─▶ GraphModel               lib/graph/types.ts
                          └─▶ aggregate          lib/aggregate.ts    →  collapse/expand view + edge evidence merge
                                └─▶ scene        lib/graph/scene.ts  →  geometry-free, signature-keyed
                                      └─▶ layout lib/layout.worker.ts→  off-main-thread, engine per cluster
                                            └─▶ Vello WebGPU canvas  vello-renderer/ (Rust → WASM)
  1. Input. The client sends a folder path (or, in the web fallback, a read-in-browser file map) to the Bun analysis sidecar — a loopback HTTP server. /scan reads the path from disk; nothing leaves the machine. See Getting Started.
  2. Kernel. analyzeProject(files) buckets files by extension and runs every matching language provider concurrently (Promise.all), then merges their fragments, de-duplicates, and drops edges to unknown nodes. See Language Analysis.
  3. View + layout. The client projects the merged GraphModel into a collapse/expand view, builds a geometry-free scene, and lays it out in a Web Worker. See Layout Engine Internals.
  4. Render. A Vello (Rust → WASM, WebGPU) canvas draws cards, edges, and text as GPU vectors, scaling to thousands of nodes. See Rendering & Performance.

The three load-bearing seams

Almost everything in PolyGraph hangs off three clean interfaces. Understanding these three is most of understanding the codebase.

1. The provider boundary — analyzeProject(files) → GraphModel

The language kernel is decoupled from the UI behind exactly one function. Each language is a provider plugin registered in lib/kernel/registry.ts. Two kinds exist:

  • TypeScript / JavaScript → a precise, ts-morph-backed provider (lib/analyzer/) that uses the TypeScript type checker for type-resolved call edges, JSX/renders detection, and framework/paradigm roles.
  • Everything else → declarative tree-sitter packs (language-packs/<id>/) run by a native Rust core (analyzer-core/, napi-rs).

A provider can start as a declarative pack and later graduate to a precise, code-backed provider without changing anything else. That's the whole point of the boundary. A single provider throwing is caught and surfaced as an error rather than failing the entire analysis.

2. The geometry-free scene — shared by layout and renderer

lib/graph/scene.ts builds a scene that carries node/edge identity, styling, and a signature (a string of every input that affects layout) — but no positions. The signature is a cache key: an unchanged scene reuses its computed positions, and the previous positions are threaded into a new layout to preserve the visual "mental map" when you re-filter or zoom. Layout fills in geometry; the renderer consumes it.

3. The native / WASM split — two Rust crates

Two performance-critical pieces are Rust, both shipped as committed prebuilt artifacts so the app runs without a Rust toolchain:

  • analyzer-core/ — a napi-rs addon (analyzer-core.node) running tree-sitter. Loaded via process.dlopen by absolute path (not require, which webpack would try to bundle).
  • vello-renderer/ — a Rust → WASM crate exposing the WebGPU VelloCanvas. Loaded client-side via dynamic import() (WebGPU is browser-only).

Subsystem map

Area Where Wiki page
Sidecar + scan/analyze sidecar/server.ts, lib/server/ Getting Started
Language kernel + providers lib/kernel/, lib/analyzer/, analyzer-core/, language-packs/ Language Analysis
Graph types + edge evidence lib/graph/types.ts The Graph Model
View projection lib/aggregate.ts The Graph Model
Scene + layout lib/graph/scene.ts, lib/layout.ts, lib/layout/ Layout Engine Internals
Renderer vello-renderer/ Rendering & Performance
Impact analysis lib/graph/query.ts Impact Analysis & Insights
Insights (Problems panel) lib/graph/insights.ts Impact Analysis & Insights
Query language lib/graph/query-language/ Query Language
Abstraction levels lib/graph/levels/, lib/server/manifests/ The Graph Model
CLI: check + diff cli/, lib/cli/, lib/rules/, lib/diff/ CLI: Rules & Diff
Exports + workspaces lib/export/, lib/workspace/ Exports, Workspaces & Editor
Editor integration + Tauri lib/editor/, src-tauri/ Exports, Workspaces & Editor
Telemetry lib/telemetry/ Rendering & Performance
Benchmarks bench/ Development & Building

Design principles you'll see repeated

  • Local-first. No network calls in the analysis path. Source reads on desktop are constrained to the scanned project root.
  • Determinism. Community detection, SCC, component ordering, and layout seeding are all deterministic so graphs and snapshots are stable across runs.
  • Graceful degradation at scale. Every heavy step (layout, rendering, the scan response) has a budget guard and a cheaper fallback rather than a hang or crash. See Rendering & Performance.
  • Evidence, not assertions. Every edge carries where it was observed and a confidence level. See The Graph Model.

Clone this wiki locally