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

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 + Y for rapid scanning
  • Qualitative size labels — replaces raw KB noise with HIGH impact, VERY LARGE, MEDIUM impact
  • Complexity interpretation🚨 HIGH complexity / ⚠️ MODERATE complexity with hydration-cost explanations
  • Warning clusters — severity + consequence for every warning type (HIGH RISK → may break UI at runtime)
  • Discovers routes from both app/ and pages/ 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
  • --verbose flag for full dependency and component detail

Requirements

  • Node.js 18.18 or newer
  • A Next.js project using app/, pages/, or both

Install

Run without installing:

npx next-route-xray

Install globally:

npm install -g next-route-xray

Install as a project dev dependency:

npm install --save-dev next-route-xray

Then add a script:

{
  "scripts": {
    "analyze:routes": "next-route-xray"
  }
}

Usage

Analyze the current project:

next-route-xray

Analyze a specific project directory:

next-route-xray --cwd ./apps/web

Analyze one route:

next-route-xray --route /dashboard

Show full dependency lists and component details:

next-route-xray --verbose

Output JSON for CI, scripts, or dashboards:

next-route-xray --json

Output AI IDE-friendly JSON (Cursor, Copilot):

next-route-xray --agent

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

Tip: Use --verbose to see the full per-dependency breakdown and raw component lists.

JSON Output

Use --json when you want machine-readable route analysis:

next-route-xray --json

The 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 --agent

Each 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:

  • RouteAnalysis
  • ProjectHealth
  • RouteEntry
  • DependencySummary
  • DuplicateDependency
  • HeavyComponent
  • ModuleGraph
  • ModuleNode
  • DiscoveryOptions
  • RouterKind

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 contents

License

MIT