next-route-xray
v0.5.1
Published
Static pre-build route cost insights for Next.js projects.
Readme
next-route-xray
Static pre-build route cost insights and proactive decision engine for Next.js projects.
next-route-xray scans a Next.js app before build time and acts as a Decision Engine. It clusters repeated dependency issues into cross-route patterns, ranks them by leverage, and tells you exactly which fix will improve the most routes — before a single build runs.
Features
- Cross-route pattern clustering — groups repeated dependency issues (full imports, duplicates, complexity) into named patterns with severity and leverage scores
- Decision guidance — prioritizes systemic fixes over route-specific ones, showing how many routes each fix improves
- "Why it matters" explanations — user-impact bullets for every detected pattern (bundle size, hydration cost, runtime risk)
- Grouped, non-redundant fix suggestions — one fix per pattern, never repeated per dependency
- One-line route summaries — each route opens with
→ heavy due to X + Yfor rapid scanning - Qualitative size labels — replaces raw KB noise with
HIGH impact,VERY LARGE,MEDIUM impact - Complexity interpretation —
🚨 HIGH complexity/⚠️ MODERATE complexitywith hydration-cost explanations - Warning clusters — severity + consequence for every warning type (
HIGH RISK → may break UI at runtime) - Discovers routes from both
app/andpages/routers - Separate tracking for Userland vs Core Next/React bundle costs
- Reports shared, route-specific, direct, and transitive dependencies
- Detects duplicate dependency families
- Supports human-readable, JSON, and AI-agent output
--verboseflag for full dependency and component detail
Requirements
- Node.js
18.18or newer - A Next.js project using
app/,pages/, or both
Install
Run without installing:
npx next-route-xrayInstall globally:
npm install -g next-route-xrayInstall as a project dev dependency:
npm install --save-dev next-route-xrayThen add a script:
{
"scripts": {
"analyze:routes": "next-route-xray"
}
}Usage
Analyze the current project:
next-route-xrayAnalyze a specific project directory:
next-route-xray --cwd ./apps/webAnalyze one route:
next-route-xray --route /dashboardShow full dependency lists and component details:
next-route-xray --verboseOutput JSON for CI, scripts, or dashboards:
next-route-xray --jsonOutput AI IDE-friendly JSON (Cursor, Copilot):
next-route-xray --agentCLI Options
| Option | Description |
| --- | --- |
| --cwd <path> | Project directory to analyze. Defaults to the current working directory. |
| --route <route> | Analyze only one route, such as /dashboard. |
| --verbose | Show full dependency lists, component details, and raw cause breakdowns. Default output is compressed. |
| --json | Output structured JSON instead of human-readable text. |
| --agent | Output AI IDE-friendly structured JSON containing actionable code fixes. |
Example Output
📊 Project Health
- 2 critical routes
- 3 OK routes
- 1 systemic issues
- 1 critical warnings
🔥 Key Problems:
- [HIGH] Full import (tree-shaking ineffective) — affecting 4 routes
- [MEDIUM] Excessive client-side complexity — affecting 2 routes
🔥 Systemic Issues:
- lucide-react affecting 4 routes
💡 Suggested Strategy:
1. Fix "Full import (tree-shaking ineffective)" → improves 4 routes
2. Fix "Excessive client-side complexity" → improves 2 routes
3. Then optimize /conversations/[id] (route-specific)
━━ Detected Patterns ━━
📌 Pattern [HIGH]: Full import (tree-shaking ineffective)
Affects: lucide-react, @base-ui/react, tailwind-merge
Why it matters:
- pulls entire library into bundle — even unused exports
- increases initial load and parse time
- affects 4 routes
💡 Fix: Convert full imports to named imports for: lucide-react, @base-ui/react, tailwind-merge
Routes: /dashboard, /conversations/[id], /settings, /profile
━━━━━━━━━━━━━━━━━━━━━━━
Route /conversations/[id] [Severity: HIGH]
→ heavy due to lucide-react + @base-ui/react
cost Userland: 210 KB | Core (ignored): 22 KB
systemic Heavy because of lucide-react
patterns Full import (tree-shaking ineffective)
stats depth 6 | client 12 | server 2
🚨 HIGH complexity
- 12 client components → adds hydration cost
- depth 6 → refactoring recommended
ℹ️ Issues covered by patterns above — see pattern definitions for fixes.
⚠️ WARNINGS:
- 2 unresolved imports (HIGH RISK)
→ may break UI at runtime
* unresolved component ChatInput in page.tsxTip: Use
--verboseto see the full per-dependency breakdown and raw component lists.
JSON Output
Use --json when you want machine-readable route analysis:
next-route-xray --jsonThe command writes an object containing project health metrics and a routes array:
{
"projectHealth": {
"criticalRoutes": 1,
"okRoutes": 4,
"systemicIssues": [],
"criticalWarnings": 1
},
"routes": [
{
"route": "/dashboard",
"file": "/project/app/dashboard/page.tsx",
"estimatedJsKb": 106,
"bundleDetails": {
"coreJsKb": 22,
"userlandJsKb": 84
},
"severity": "HIGH",
"insights": [
{
"problem": "Large client bundle",
"rootCauses": ["recharts → VERY LARGE (likely full library included)"],
"suggestedFix": ["Convert full imports to named imports for: recharts"]
}
],
"warningClusters": [
{
"category": "unresolved imports",
"count": 1,
"severity": "HIGH",
"items": ["unresolved component Chart in dashboard/page.tsx"]
}
],
"dependencies": {
"top": [],
"direct": [],
"transitive": [],
"shared": [],
"routeSpecific": [],
"duplicates": []
},
"componentComplexity": {
"depth": 4,
"clientComponentCount": 2,
"serverComponentCount": 3,
"heavyComponents": [],
"warnings": []
},
"warnings": []
}
]
}Agent Output (AI-Executable Layer)
Use --agent when you want an actionable JSON structure optimized for AI IDEs like Cursor and Copilot:
next-route-xray --agentEach AgentAction contains everything an AI IDE needs to suggest or apply a fix:
| Field | Type | Description |
|---|---|---|
| type | string | import_optimization | architecture_change | systemic_dependency_issue | warning_resolution |
| file | string | Absolute path to the affected file |
| problem | string | Human-readable description of the issue |
| dependency | string? | Package name involved (when applicable) |
| impact | string | bundle_size | hydration_cost | stability |
| priority | string | high | medium | low |
| confidence | number | 0–1 score for how certain the diagnosis is |
| autoFixable | boolean | true when a single-file import rewrite is sufficient |
| risk | string | high | medium | low — safety of applying the fix |
| reason | string | Root cause explanation |
| fix | object? | { kind, from, to, patch } — code-level replacement |
| fix.patch | string? | Unified diff ready to apply |
| suggestedFix | string? | Prose suggestion when autoFixable is false |
| affectedFiles | string[]? | Files involved in grouped/systemic actions |
| occurrences | number? | Route count for systemic issues |
Example
{
"agentActions": [
{
"type": "import_optimization",
"file": "app/dashboard/page.tsx",
"problem": "Full import of 'recharts' — tree-shaking ineffective",
"dependency": "recharts",
"impact": "bundle_size",
"priority": "high",
"confidence": 0.9,
"autoFixable": true,
"risk": "low",
"reason": "recharts → VERY LARGE (likely full library included)",
"codeContext": "import * as Lib from 'recharts'",
"fix": {
"kind": "replace_import",
"from": "import * as Lib from 'recharts'",
"to": "import { LineChart, BarChart } from 'recharts'",
"patch": "- import * as Lib from 'recharts'\n+ import { LineChart, BarChart } from 'recharts'"
}
},
{
"type": "architecture_change",
"file": "app/conversations/[id]/page.tsx",
"problem": "Excessive client components or component tree depth",
"impact": "hydration_cost",
"priority": "high",
"confidence": 0.7,
"autoFixable": false,
"risk": "high",
"reason": "12 client components → high hydration cost | depth 6 → refactoring needed",
"suggestedFix": "isolate heavy components to client-only boundaries | move state down the tree"
},
{
"type": "systemic_dependency_issue",
"problem": "lucide-react affecting 4 routes",
"dependency": "lucide-react",
"impact": "bundle_size",
"priority": "high",
"confidence": 0.9,
"autoFixable": false,
"risk": "medium",
"reason": "Package causes systemic bundle size issues across multiple routes.",
"occurrences": 4,
"affectedFiles": [
"app/dashboard/page.tsx",
"app/conversations/[id]/page.tsx"
],
"suggestedFix": "Avoid using this package or switch to selective/named imports."
}
]
}Action priority and sorting
Actions are returned sorted by priority (high → low) then confidence (high → low), so the first action in the array is always the most impactful and certain fix to apply first.
How Pattern Clustering Works
next-route-xray runs a pattern engine after analysis to group repeated causes across routes:
| Pattern | Triggered by | Severity scaling |
|---|---|---|
| Full import (tree-shaking ineffective) | Non-core dep with estimatedKb > 20 | LOW → HIGH based on route count |
| Excessive client-side complexity | clientComponentCount > 10 or depth > 5 | MEDIUM → HIGH based on route count |
| Duplicate dependency versions | Duplicate dep families detected | LOW → MEDIUM based on route count |
In default (compressed) mode, per-route cards reference pattern names instead of repeating dependency lists. Run --verbose to see the full breakdown per route.
Programmatic API
import { analyzeRoutes, discoverRoutes } from "next-route-xray";
const cwd = process.cwd();
const routes = await discoverRoutes({ cwd });
const results = await analyzeRoutes(cwd, routes);
console.log(results);Exported TypeScript types:
RouteAnalysisProjectHealthRouteEntryDependencySummaryDuplicateDependencyHeavyComponentModuleGraphModuleNodeDiscoveryOptionsRouterKind
Notes
Estimated JavaScript sizes are static heuristics, not a replacement for Next.js production build analysis. Use this tool as an early warning system during development, code review, and CI.
For exact production bundle details, pair it with your Next.js build output or a bundle analyzer.
Development
npm install # install dependencies
npm run dev # run CLI from source
npm run build # build TypeScript
npm run typecheck # type-check
npm test # run tests
npm pack --dry-run # preview package contentsLicense
MIT
