arch-atlas
v0.2.1
Published
Interactive architecture explorer for React, Next.js, and React Native codebases
Maintainers
Readme
Arch Atlas
See your app’s architecture — screens, components, hooks, and how they connect.
Arch Atlas is an interactive architecture explorer for JavaScript and TypeScript projects. It scans your app with static analysis (no code execution), builds a dependency graph, and launches a local web UI where you can explore screens, components, hooks, routes, packages, and how everything connects.
Works with React, Next.js, Expo, Expo Router, and React Native CLI projects — including monorepos.

Quick Start Commands
Use the command that matches where you are running from:
| Scenario | Command to Run | What It Loads |
|----------|----------------|---------------|
| Inside the project you want to analyze (entire project) | npx arch-atlas | Entire current project |
| Outside the project you want to analyze (entire project) | npx arch-atlas --project /path/to/your/project | Entire project at the given path |
| Outside a project, but only scan a directory subtree | npx arch-atlas --project /path/to/your/project/components | Only that directory (for example, just components) |
| Inside a project, but only pull a file | npx arch-atlas --pull components/TabLayout.tsx | That file plus linked dependency chain |
| Outside a project, and only pull one area | npx arch-atlas --project /path/to/your/project --pull src/hooks | Pulled subset from the specified project |
npm install -D arch-atlas
npx arch-atlasOpens http://localhost:4578 in your browser.
Table of Contents
- Why Arch Atlas?
- Features
- Supported Projects
- Requirements
- Installation
- Usage
- CI / scan-only mode
- CLI Reference
- Web Explorer
- How It Works
- What to Expect
- Limitations
- Roadmap
- Development
- Changelog highlights (v0.1.8)
- License
Why Arch Atlas?
Most dependency tools show you a flat graph of imports. Arch Atlas is built to help you understand your application architecture:
- Which screens exist and how navigation flows
- What a component imports, who imports it, and which hooks it uses
- Which npm packages are used where
- What code is unused (and why), or part of a circular dependency
- What would break if you change a file (impact / reverse dependents)
- How monorepo packages depend on each other — including deep imports
- How folders compare in size, coupling, and complexity
It is designed for developer experience first — fast search, clear highlighting, live updates as you edit files, and a UI that feels good to explore. CI flags make the scan sticky in team pipelines.
Features
Interactive Architecture Graph
- Full-project dependency graph rendered with pan, zoom, and minimap
- Nodes typed by kind: components, screens, hooks, providers, packages, routes, assets, layers
- Click any node to highlight its connections:
- Purple — files/packages it imports (outgoing)
- Cyan — files that import it (incoming)
- Unrelated nodes fade so you can focus
- Import heatmap — heavily used files stand out visually
- Circular dependencies highlighted in red
Component Inspector
Click any file node to open the inspector panel:
- Impact if changed — reverse dependency tree (who breaks if you edit/delete this file), depth-limited
- Imported by — every file that depends on it (click to jump)
- Imports — local files and npm packages
- Hooks —
useState, custom hooks, etc. (custom hooks badged) - Contexts —
createContextand Provider usage - Metadata — layer, line count, state libraries
Navigation Explorer
Automatically detects routing for:
- Expo Router —
app/directory, layouts, nested routes - React Navigation — stacks, tabs, drawers, screen files
- Next.js App Router —
page.tsx,layout.tsx, route segments - Next.js Pages Router —
pages/directory
Visual route flow view — click a route to select it in the graph.
Package Explorer
- Every npm dependency ranked by file usage
- Top consumers per package
- Symbols imported (
useAnimatedStyle,useQuery, etc.) - Usage bars for quick comparison
Package boundaries (monorepos)
- Cross-package imports under
apps/,packages/,libs/,modules/,services/ - Who depends on each workspace package
- Deep imports that skip a package’s public entry (e.g.
packages/ui/src/Button)
Dead Code & Issues
- Unused files — never imported and not a framework entry point
- “Why is this dead?” — expandable checks: not an entry, not a route, unreachable from entries, no importers, not a live platform sibling
- Circular dependencies — full cycle paths listed
- Framework routes (Next.js pages, Expo Router screens) are excluded — they are loaded by convention, not imports
- Grouped by directory with collapse / expand
- Open unused files directly in your editor
Ignore patterns (.arch-atlasignore)
Skip noise by default (tests, stories, *.d.ts, __mocks__, e2e folders). Add a .arch-atlasignore in your project root (gitignore syntax) for more control. See .arch-atlasignore.example.
Graph filters & export
- Filter by kind and architecture layer
- Focus on 1–2 hop neighborhoods around the selected node
- Export the graph as JSON or PNG
CI gates
Fail the process in pipelines when circular deps exist or unused-file count exceeds a threshold. See CI / scan-only mode.
Folder Heatmap
Per-folder stats:
- File count
- Total lines (complexity proxy)
- Outgoing dependency count
- Coupling (incoming references)
Global Search
Instantly find components, screens, hooks, packages, routes, and files. Click a result to jump to it in the graph.
Live Mode
Filesystem watcher with debounced rescans. When you save a file:
- Graph updates automatically via WebSocket
- No manual refresh needed
- "Live" indicator shown in the header
Light & Dark Mode
Toggle in the header. Preference saved in localStorage.
Supported Projects
| Framework | Detection | Notes |
|-----------|-----------|-------|
| Expo Router | expo-router dependency or app/ + Expo | Route files, layouts, nested groups |
| Expo | expo in dependencies | Standard entry points |
| React Native CLI | react-native or metro.config.js | Screens, navigators |
| Next.js | next in dependencies | App Router + Pages Router |
| Plain React | Falls back to unknown | Import graph still works |
| Monorepos | npm/yarn/pnpm workspaces, Nx, Turbo | Workspace-aware scanning |
Also detected
- TypeScript path aliases (
tsconfig/jsconfigpaths) - Package manager (npm, yarn, pnpm)
- State libraries in imports: Redux, Zustand, Jotai, MobX, Recoil, TanStack Query
- Dynamic imports,
require(),React.lazy(() => import(…)), andrequire.context(…) - Entry points from
package.jsonmain/react-native/module, ExpoentryPoint,app.config.*, Nextmiddleware - Metro/Expo platform siblings (
.ios,.android,.web,.native, …) - Type-only imports (
import type) — excluded from the runtime graph so they don’t inflate edges
Scanned file types
.ts · .tsx · .js · .jsx
Ignored directories
node_modules · android · ios · .expo · .next · dist · build · coverage · .git · .venv · and more
Requirements
- Node.js >= 18
- A JavaScript/TypeScript project on your local filesystem
- A modern browser (Chrome, Firefox, Safari, Edge)
Installation
As a dev dependency (recommended)
npm install -D arch-atlas
# or
yarn add -D arch-atlas
# or
pnpm add -D arch-atlasOne-off without installing
npx arch-atlasUsage
Start the explorer (default)
From your project root:
npx arch-atlasOr point at any project:
npx arch-atlas --project /path/to/your/appThis command scans the entire project graph.
This will:
- Discover your project type and entry points
- Parse all source files with AST analysis
- Build the architecture graph
- Start a local server at
http://localhost:4578 - Open your browser automatically
Press Ctrl+C to stop.
Scan without starting the UI
Useful for CI checks or quick stats:
npx arch-atlas --scan-only
npx arch-atlas --scan-only --project ./apps/mobileStart with a pulled graph
Load only a specific file or folder and its dependency chain:
npx arch-atlas --pull components/TabLayout.tsx
npx arch-atlas --pull src/hooks
npx arch-atlas --project /path/to/your/app --pull app/(tabs)/_layout.tsxThis is useful in very large projects when you want to inspect one area quickly.
Example output:
Project: my-app (expo-router)
Files: 396
Components: 156
Screens: 70
Hooks: 57
Packages: 81
Dead code: 75
Circular: 4
Scan time: 4200msCI / scan-only mode
Use these flags in GitHub Actions, CI jobs, or pre-merge checks. They scan and exit (no UI server). Exit code 1 when a gate fails.
# Fail if any circular dependency is found
npx arch-atlas --scan-only --fail-on-circular
# Fail if unused files exceed a threshold
npx arch-atlas --scan-only --max-dead-code 50
# Combine gates + machine-readable JSON
npx arch-atlas --scan-only --json --fail-on-circular --max-dead-code 100--fail-on-circular / --max-dead-code imply a scan-only run (you can omit --scan-only).
Example GitHub Actions step:
- name: Architecture gates
run: npx arch-atlas --scan-only --fail-on-circular --max-dead-code 80CLI Reference
Usage: arch-atlas [options]
Options:
-p, --project <path> Project root directory (default: current directory)
--pull <target> Pull a file/folder and its dependency chain into the graph
--port <number> Server port (default: 4578)
--no-open Do not open browser automatically
--no-watch Disable live filesystem watching
--scan-only Print scan stats and exit (no server)
--json With --scan-only, print a JSON summary
--fail-on-circular Exit 1 if circular dependencies are found (CI)
--max-dead-code <n> Exit 1 if unused files exceed this count (CI)
-h, --help Display help
-V, --version Display versionExamples
# Custom port, no browser
npx arch-atlas --port 3001 --no-open
# Large monorepo app
npx arch-atlas --project ./apps/web
# Pull graph around one file
npx arch-atlas --pull components/TabLayout.tsx
# Pull while running from outside a project
npx arch-atlas --project ./apps/web --pull src/components/TabLayout.tsx
# CI: circular + dead-code threshold
npx arch-atlas --scan-only --fail-on-circular --max-dead-code 50
# CI: JSON report for scripts
npx arch-atlas --scan-only --json --fail-on-circularWeb Explorer
Once running, the UI has these views (left sidebar):
| View | Description | |------|-------------| | Architecture | Interactive dependency graph | | Navigation | Route flow for your router | | Packages | npm package usage ranked by adoption | | Boundaries | Monorepo cross-package edges and deep imports | | Dead Code | Unused files (with “why?”) and circular dependencies | | Folders | Per-folder complexity heatmap |
Graph interactions
| Action | Result | |--------|--------| | Click a node | Select it, highlight connections, open inspector | | Click empty canvas | Clear selection | | Scroll | Zoom in/out | | Drag | Pan the graph | | Search bar | Find any symbol, file, or package | | Inspector panel (right) | Full detail for selected node |
Connection legend (when a node is selected)
| Color | Meaning | |-------|---------| | Purple | Imports (outgoing dependencies) | | Cyan | Imported by (incoming dependencies) | | Red | Circular dependency edge |
How It Works
Arch Atlas uses static AST parsing — your app is never executed.
Your Project
│
▼
@arch-atlas/core ts-morph AST parser
│ • imports / exports / dynamic imports
│ • hooks, contexts, components
│ • navigation & framework route detection
│ • dead code & circular dependency analysis
▼
ArchitectureGraph nodes + edges + metadata
│
▼
@arch-atlas/server Fastify API + WebSocket + chokidar watcher
│
▼
@arch-atlas/web React + React Flow interactive UIArchitecture layers
Files are automatically classified:
presentation · business · state · networking · storage · utilities · assets · navigation
Framework route awareness
Files loaded by convention (not imports) are treated as entry points:
- Next.js:
pages/**,app/**/page.tsx,layout.tsx,middleware.ts - Expo Router:
app/**route files and_layout.tsx
This prevents false "dead code" reports for pages and screens.
What to Expect
Scan times
| Project size | Typical first scan | |--------------|-------------------| | Small (< 50 files) | 1–5 seconds | | Medium (50–200 files) | 5–20 seconds | | Large (200–500 files) | 20–60 seconds | | Very large (500+ files) | 1–3 minutes |
Subsequent live updates are incremental and much faster (only changed files are re-parsed).
Graph density
Large projects produce dense graphs. Use search and click-to-highlight to navigate rather than trying to read the full graph at once. The inspector panel is the primary way to explore individual files.
Local only
Arch Atlas runs entirely on your machine. No code is sent to any external server. The explorer binds to 127.0.0.1 by default.
Limitations
Arch Atlas is under active development (v0.1.8). Be aware of the following:
Analysis
- Static analysis only — runtime-only imports (e.g. fully dynamic
import(variable)) are not resolved - No bundle size data — import weight and metro/webpack bundle analysis are not yet implemented
- Alias resolution — supports
tsconfigpaths; custom webpack/babel aliases may not fully resolve - Barrel files — re-exports (
export … from) are followed for dead-code reachability; deep barrel chains can still make the graph denser than direct imports - Platform files — Metro/Expo variants (
.ios,.android,.web,.native, …) are treated as used when the base module is imported or reachable - Dead code is heuristic — "never imported" does not mean "safe to delete" (entry points, runtime registration, and native modules may be missed)
- False positives — some framework patterns (API routes, middleware, config files) may still appear as dead code in edge cases
UI
- Large graphs — projects with 500+ files may feel slow in the browser; graph virtualization is planned
- Auto-layout is basic — nodes are grouped by architecture layer, not force-directed or ELK-optimized
- No git history — time-travel and architecture diffs are not yet available
- SVG export — PNG and JSON are supported; SVG export is not yet available
Platforms
- No Vue, Svelte, or Angular support currently
- Native modules (
.kt,.swift,.m) are not analyzed - Backend-only Node projects work for import graphs but have limited route/screen detection
Monorepos
- Workspace detection works for npm/yarn/pnpm workspaces, Nx, and Turbo
- Very large monorepos should be scanned per-app (
--project ./apps/mobile) for best performance
Roadmap
Shipped in v0.1.8 (and earlier):
- [x] Custom ignore patterns (
.arch-atlasignore) - [x] Graph filters (kind / layer) and focus neighborhood
- [x] Export graph as PNG / JSON
- [x] Open file in editor from the UI
- [x] Dead-code explainability (“why is this unused?”)
- [x] Impact view (reverse dependency tree)
- [x] CI flags (
--fail-on-circular,--max-dead-code,--json) - [x] Monorepo package boundary view
- [x] Type-only import handling,
React.lazy, richer entry detection
Still planned:
- [ ] Git integration — architecture diff over time
- [ ] Bundle size insights per screen and package
- [ ] State flow visualization (Redux, Zustand, Jotai wiring)
- [ ] AI-powered suggestions (duplicate components, lazy-load candidates)
- [ ] Graph virtualization for 10,000+ file projects
- [ ] ELK / dagre automatic layout
- [ ] VS Code extension
- [ ] SVG export
Development
Arch Atlas is a monorepo:
| Package | Version | Description |
|---------|---------|-------------|
| @arch-atlas/core | 0.1.8 | AST scanner, graph engine, analyzers |
| @arch-atlas/server | 0.1.8 | Fastify API + WebSocket live updates |
| @arch-atlas/web | 0.1.8 | React + Vite explorer UI (private; bundled into server) |
| arch-atlas | 0.1.8 | CLI (npx arch-atlas) |
Clone and run locally
git clone https://github.com/phemymii/arch-atlas.git
cd arch-atlas
npm install
npm run build
npx arch-atlas --project /path/to/your/appScripts
npm run build # Build core → web → server → cli
npm run test # Core fixture tests (Expo / Next / RN / monorepo)
npm run dev # Vite UI (proxies API to :4578)
npm run arch-atlas # Run built CLIRun the web UI in dev mode
npm run arch-atlas -- --project /path/to/app --no-open # API on :4578
npm run dev # Vite on :5173API endpoints
When the server is running:
| Endpoint | Description |
|----------|-------------|
| GET /api/health | Server status and project path |
| GET /api/graph | Full architecture graph (includes deadCode, packageBoundaries, …) |
| GET /api/file/* | File detail (imports, hooks, contexts) |
| GET /api/package/:name | Package usage detail |
| GET /api/dependencies/* | Forward dependency tree (?depth=3) |
| GET /api/impact/* | Reverse impact tree — who depends on this file (?depth=3) |
| GET /api/boundaries | Monorepo package boundary report |
| GET /api/search?q= | Search index |
| GET /api/dead-code | Dead code list (with explanations) |
| GET /api/circular | Circular dependencies |
| POST /api/open | Open a file path in the local editor |
| POST /api/rescan | Trigger full rescan |
| WS /ws | Live graph updates |
Library consumers: see packages/core/README.md and packages/server/README.md.
Changelog highlights (v0.1.8)
- Dead-code explainability — structured checks in the UI and
DeadCodeItem.explanation - Impact view — reverse dependents in the inspector +
getImpactTree//api/impact - CI mode —
--fail-on-circular,--max-dead-code,--json - Package boundaries — Boundaries view +
packageBoundarieson the graph - Accuracy — type-only imports,
React.lazy,require.context, richer entries (main, middleware,app.config) - Fixtures —
npm testcovers Expo Router, Next.js, RN CLI, and monorepo deep imports
FAQ
Does this modify my project?
No. Arch Atlas is read-only. It only reads files and starts a local server.
Can I use it in CI?
Yes. Prefer exit codes over grepping:
npx arch-atlas --scan-only --fail-on-circular --max-dead-code 50Or parse --json output in a script.
Why are some pages showing as dead code?
Framework routes (Next.js pages, Expo Router screens) are excluded automatically. Use Why is this dead? on the Dead Code view to see which checks failed. If a file still appears, it may be loaded dynamically or registered outside the import graph. Open an issue with the file path.
Does it work with TypeScript path aliases?
Yes, if they are defined in tsconfig.json or jsconfig.json compilerOptions.paths.
What port does it use?4578 by default. Change with --port.
License
MIT
