codeviz
v0.1.4
Published
Interactive 2D codebase visualization with hierarchical semantic zoom
Maintainers
Readme
CodeViz
Interactive 2D codebase visualization with hierarchical semantic zoom
CodeViz is a React component library for visualizing codebases as interactive 2D maps. It provides developers with an intuitive, map-like interface for understanding code structure, dependencies, and relationships at multiple levels of abstraction.
Features
- Hierarchical Visualization - Directories as nested containment regions (scopes)
- Semantic Zoom - 5 discrete zoom levels showing different information density
- Multi-Language Support - TypeScript, JavaScript, Python via tree-sitter parsing
- Dependency Visualization - Import and call graph relationships as edges
- Overlay System - Cursors, badges, annotations for collaboration
- Theme Support - Light and dark themes with full customization
- Dual Renderers - React Flow (default) or Sigma.js (WebGL) for large graphs
- High Performance - Supports codebases up to 10,000+ files with Sigma renderer
Quick Start
npm install codevizimport { CodeMapComponent, useLayout, analyzeCodebase } from 'codeviz';
function App() {
const [codeGraph, setCodeGraph] = useState(null);
useEffect(() => {
analyzeCodebase('./src').then(result => {
setCodeGraph(result.codeGraph);
});
}, []);
const { codeMap, isComputing } = useLayout(codeGraph);
if (isComputing || !codeMap) {
return <div>Loading...</div>;
}
return (
<CodeMapComponent
codeMap={codeMap}
theme="dark"
onNodeClick={(node) => console.log('Clicked:', node)}
/>
);
}Installation
# npm
npm install codeviz
# yarn
yarn add codeviz
# pnpm
pnpm add codevizPeer Dependencies
CodeViz requires React 18+:
npm install react react-domUsage
Analyzing a Codebase
Use analyzeCodebase to scan and parse source files:
import { analyzeCodebase } from 'codeviz';
const result = await analyzeCodebase('./src', {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
ignorePatterns: ['node_modules', 'dist', '*.test.ts'],
maxDepth: 10,
});
// result.codeGraph contains:
// - files: FileNode[]
// - directories: DirectoryNode[]
// - symbols: SymbolNode[]
// - imports: ImportEdge[]
// - calls: CallEdge[]Computing Layout
Transform a CodeGraph into positioned CodeMap:
import { useLayout, computeLayout } from 'codeviz';
// React hook (recommended)
const { codeMap, isComputing, error } = useLayout(codeGraph, {
algorithm: 'force-directed',
clusteringEnabled: true,
});
// Or imperative API
const codeMap = await computeLayout(codeGraph, layoutConfig);Rendering the Map
import { CodeMapComponent } from 'codeviz';
<CodeMapComponent
codeMap={codeMap}
theme="dark"
// Interaction callbacks
onNodeClick={(node) => handleNodeClick(node)}
onNodeHover={(node) => handleNodeHover(node)}
onScopeToggle={(scopeId, expanded) => handleScopeToggle(scopeId, expanded)}
onViewportChange={(viewport) => handleViewportChange(viewport)}
onZoomLevelChange={(level) => handleZoomLevelChange(level)}
// Selection (controlled)
selectedNodes={['file-1', 'file-2']}
onSelectionChange={(nodeIds) => setSelectedNodes(nodeIds)}
/>Using Overlays
Add cursors, badges, and annotations:
import { useOverlayPort, CodeMapComponent } from 'codeviz';
function CollaborativeMap({ codeMap }) {
const { port, overlays } = useOverlayPort();
// Add a cursor overlay
const cursorId = port.bind({
type: 'cursor',
position: { type: 'absolute', x: 100, y: 200 },
color: '#6366f1',
label: 'Alice',
});
// Add a badge to a node
port.bind({
type: 'badge',
position: { type: 'node', nodeId: 'file-1', anchor: 'top-right' },
variant: 'count',
value: 3,
});
// Update cursor position
port.update(cursorId, {
position: { type: 'absolute', x: 150, y: 250 },
});
return (
<CodeMapComponent
codeMap={codeMap}
overlayPort={port}
onOverlayClick={(id, overlay) => console.log('Overlay clicked:', id)}
/>
);
}Sigma Renderer (WebGL)
For large codebases (1,000+ files), use the Sigma.js renderer for better performance:
import { CodeMap } from 'codeviz';
<CodeMap
codeMap={codeMap}
codeGraph={codeGraph} // Required for nexus view
renderer="sigma" // Use WebGL renderer
view="structure" // "structure" or "nexus"
theme="dark"
onNodeClick={(nodeId, node) => console.log('Clicked:', nodeId)}
/>View Modes
| Mode | Description | Data Source | Best For |
|------|-------------|-------------|----------|
| structure | File system hierarchy with scopes | CodeMap | Understanding project organization |
| nexus | Flat relationship graph | CodeGraph | Exploring dependencies and imports |
When to Use Sigma vs React Flow
| Scenario | Recommended Renderer | |----------|---------------------| | < 500 nodes | React Flow (richer interactions) | | 500 - 2,000 nodes | Either (test both) | | 2,000+ nodes | Sigma (WebGL performance) | | Need nested scopes | React Flow | | Need force-directed layout | Sigma |
Sigma-Specific Features
import { SigmaRenderer } from 'codeviz';
// Direct Sigma renderer access (advanced)
<SigmaRenderer
graph={graphologyGraph}
view="nexus"
theme={darkTheme}
// Selection
selectedNodeId={selectedNode}
onSelectedNodeChange={setSelectedNode}
// Highlights (e.g., from AI/search)
highlightedNodeIds={['file-1', 'file-2']}
// Controls
showControls={true}
controlsPosition="bottom-right"
// Overlays work with Sigma too
overlays={overlays}
onOverlayClick={handleOverlayClick}
/>Imperative API
import { useRef } from 'react';
import { SigmaRenderer, SigmaRendererHandle } from 'codeviz';
function MyComponent() {
const sigmaRef = useRef<SigmaRendererHandle>(null);
const handleFocus = () => {
sigmaRef.current?.focusNode('file-1');
};
const handleFitAll = () => {
sigmaRef.current?.fitToNodes(['file-1', 'file-2', 'file-3']);
};
return (
<>
<SigmaRenderer ref={sigmaRef} ... />
<button onClick={handleFocus}>Focus Node</button>
<button onClick={() => sigmaRef.current?.zoomIn()}>Zoom In</button>
<button onClick={() => sigmaRef.current?.resetView()}>Reset</button>
</>
);
}Zoom Levels
CodeViz uses 5 semantic zoom levels:
| Level | Name | Zoom Range | Content | |-------|------|------------|---------| | 0 | Overview | 0 - 0.25 | Top directories only, aggregated edges | | 1 | Modules | 0.25 - 0.5 | Subdirectories + large files (>200 LOC) | | 2 | Files | 0.5 - 1.0 | All files + exported symbols | | 3 | Symbols | 1.0 - 2.0 | All symbols + call graph edges | | 4 | Code | 2.0+ | Code preview panels, all details |
Configuration
Layout Configuration
import { computeLayout, DEFAULT_LAYOUT_CONFIG } from 'codeviz';
const layoutConfig = {
...DEFAULT_LAYOUT_CONFIG,
// Clustering
clusteringEnabled: true,
clusteringResolution: 1.0,
// Force-directed layout
forceIterations: 100,
forceGravity: 0.1,
forceRepulsion: 1.0,
// Sizing
nodeSizeBase: 40,
nodeSizeScale: 1.5,
scopePadding: { top: 40, right: 20, bottom: 20, left: 20 },
};
const codeMap = await computeLayout(codeGraph, layoutConfig);Theme Customization
import { CodeMapComponent, darkTheme, mergeTheme } from 'codeviz';
const customTheme = mergeTheme(darkTheme, {
colors: {
nodes: {
file: { background: '#1e293b', border: '#334155' },
},
scopes: {
depth0: '#0f172a',
depth1: '#1e293b',
depth2: '#334155',
},
},
});
<CodeMapComponent codeMap={codeMap} theme={customTheme} />API Overview
Components
| Component | Description |
|-----------|-------------|
| CodeMapComponent | Main visualization component (React Flow renderer) |
| CodeMap | Unified component supporting both renderers |
| SigmaRenderer | WebGL-based Sigma.js renderer |
| ThemeProvider | Theme context provider |
| OverlayLayer | Overlay rendering layer |
| GraphControls | Zoom/pan controls for Sigma renderer |
Hooks
| Hook | Description |
|------|-------------|
| useLayout | Compute layout from CodeGraph |
| useOverlayPort | Manage overlay state |
| useTheme | Access current theme |
Core Functions
| Function | Description |
|----------|-------------|
| analyzeCodebase | Scan and parse source files |
| computeLayout | Transform CodeGraph to CodeMap |
| createOverlayPort | Create imperative overlay controller |
Types
import type {
// Input types
CodeGraph,
FileNode,
DirectoryNode,
SymbolNode,
// Output types
CodeMap,
MapNode,
MapScope,
MapEdge,
// Configuration
LayoutConfig,
ZoomLevelConfig,
Theme,
// Overlays
Overlay,
CursorOverlay,
BadgeOverlay,
AnnotationOverlay,
} from 'codeviz';Storybook
Explore components interactively:
npm run storybookVisit http://localhost:6006 to see:
- CodeMap with sample data
- Theme comparisons (light/dark)
- Overlay demonstrations
- Hook integration examples
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests once
npm run test:run
# Type checking
npm run typecheck
# Build library
npm run build
# Start Storybook
npm run storybookContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Run tests (
npm test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE for details.
Acknowledgments
Built with:
- React Flow - React library for node-based UIs
- Sigma.js - WebGL graph visualization
- tree-sitter - Incremental parsing system
- graphology - Graph data structure
- ELK - Eclipse Layout Kernel
- Lucide - Icon library
