npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

arch-atlas

v0.2.1

Published

Interactive architecture explorer for React, Next.js, and React Native codebases

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.

Arch Atlas demo

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-atlas

Opens http://localhost:4578 in your browser.


Table of Contents


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
  • HooksuseState, custom hooks, etc. (custom hooks badged)
  • ContextscreateContext and Provider usage
  • Metadata — layer, line count, state libraries

Navigation Explorer

Automatically detects routing for:

  • Expo Routerapp/ directory, layouts, nested routes
  • React Navigation — stacks, tabs, drawers, screen files
  • Next.js App Routerpage.tsx, layout.tsx, route segments
  • Next.js Pages Routerpages/ 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 / jsconfig paths)
  • Package manager (npm, yarn, pnpm)
  • State libraries in imports: Redux, Zustand, Jotai, MobX, Recoil, TanStack Query
  • Dynamic imports, require(), React.lazy(() => import(…)), and require.context(…)
  • Entry points from package.json main / react-native / module, Expo entryPoint, app.config.*, Next middleware
  • 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-atlas

One-off without installing

npx arch-atlas

Usage

Start the explorer (default)

From your project root:

npx arch-atlas

Or point at any project:

npx arch-atlas --project /path/to/your/app

This command scans the entire project graph.

This will:

  1. Discover your project type and entry points
  2. Parse all source files with AST analysis
  3. Build the architecture graph
  4. Start a local server at http://localhost:4578
  5. 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/mobile

Start 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.tsx

This 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:  4200ms

CI / 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 80

CLI 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 version

Examples

# 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-circular

Web 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 UI

Architecture 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 tsconfig paths; 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/app

Scripts

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 CLI

Run the web UI in dev mode

npm run arch-atlas -- --project /path/to/app --no-open   # API on :4578
npm run dev                                              # Vite on :5173

API 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 + packageBoundaries on the graph
  • Accuracy — type-only imports, React.lazy, require.context, richer entries (main, middleware, app.config)
  • Fixturesnpm test covers 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 50

Or 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