Search by

projecthanif / routescope

projecthanif

A Laravel package for route debugging and analysis.

Package info

github.com/projecthanif/routescope

pkg:composer/projecthanif/routescope

Statistics

Installs: 1 680

Dependents: 0

Suggesters: 0

Stars: 7

Open Issues: 0

3.0.0 2026-09-28 12:51 UTC

This package is auto-updated.

Last update: 2026-09-28 13:06:15 UTC


README

A powerful route inspection tool for Laravel developers.

RouteScope gives you instant visibility into your application's routing layer. Stop guessing which routes exist, what middleware they use, or where they're defined. See everything at a glance with an elegant dashboard or query routes programmatically.

Latest Version on Packagist Total Downloads

Why RouteScope?

🔍 Instant Route Visibility

Ever wondered "Does this route actually exist?" or "What middleware is protecting this endpoint?" RouteScope answers these questions instantly with a clean, organized view of every route in your application.

🎯 Smart Organization

Routes are automatically categorized into API and web routes, making it easy to understand your application's structure at a glance. No more scrolling through php artisan route:list output.

🚀 Developer Productivity

  • Debug faster - Quickly identify routing issues and middleware conflicts
  • Onboard easier - New team members can explore the API surface in minutes
  • Document better - Generate route documentation programmatically
  • Refactor confidently - See the full scope of changes when restructuring routes

🛡️ Production-Safe

Built with safety in mind. RouteScope automatically disables itself in production environments and can be installed as a dev dependency to keep your production builds lean.

Installation

Install as a development dependency:

composer require projecthanif/routescope --dev

The package auto-registers via Laravel's service provider discovery. No additional setup required!

Quick Start

Visit the dashboard in your browser:

http://localhost/routescope

That's it! You'll see all your routes organized, searchable, and ready to explore.

Configuration

Need to customize? Publish the configuration file:

php artisan vendor:publish --tag=routescope-config

Edit config/routescope.php:

return [
    // null (the default) enables it in local/development only
    'enabled' => env('ROUTESCOPE_ENABLED'),
    
    // Customize the dashboard URL
    'prefix' => env('ROUTESCOPE_PREFIX', 'routescope'),

    // Middleware applied to the dashboard
    'middleware' => ['web'],

    // Hide routes you don't want to see (debug tools, internal routes, etc.).
    // A pattern hides the path and everything beneath it ("telescope" hides
    // "telescope/requests" but not "telescopes") and supports `*` wildcards.
    // RouteScope's own routes are always hidden.
    'excluded_patterns' => [
        '_ignition',
        'sanctum/csrf-cookie',
        'telescope',
        '_debugbar',
        '_boost',
        '__execute-laravel-error-solution',
    ],
];

To customize the dashboard itself, publish the views:

php artisan vendor:publish --tag=routescope-views

Open in Editor

Set ROUTESCOPE_EDITOR (or Laravel's own app.editor) and each route's file:line on the dashboard opens in your editor:

ROUTESCOPE_EDITOR=phpstorm   # or vscode, cursor, zed, sublime, idea, windsurf, ...

editor also accepts Laravel's array format, e.g. ['name' => 'vscode', 'base_path' => '/Users/me/code/app'] when the app runs in Docker or Sail and your editor sees the project at a different path, or ['href' => 'myeditor://open?file={file}&line={line}'] for any other editor.

Authorization

In the local environment the dashboard is open. Anywhere else (e.g. staging with ROUTESCOPE_ENABLED=true) access is denied unless the viewRouteScope gate passes. Define it in a service provider:

use Illuminate\Support\Facades\Gate;

Gate::define('viewRouteScope', function ($user = null) {
    return in_array($user?->email, ['admin@example.com'], true);
});

Features

📊 Interactive Dashboard

A beautiful, responsive interface that displays:

  • HTTP methods (GET, POST, PUT, DELETE, PATCH)
  • Route URIs and named routes (one row per route, with all of its methods)
  • Controller actions or closure definitions
  • Applied middleware
  • Search across path, method, name, middleware and source
  • Filters for HTTP method, middleware, domain, routes without authentication ("No auth", using audit.auth_middleware) and unnamed routes
  • Routes grouped by path prefix, with audit issues flagged on each route
  • Expandable details: action, file:line (opens in your editor), parameters and the middleware execution order
  • Copy a path, or open parameter-free GET routes in a new tab
  • Shareable URLs: the view, search, filters and the expanded route are kept in the query string (e.g. /routescope?view=api&noauth=1&route=GET+/api/users), so you can bookmark a filtered view or link a teammate to a specific route

🔌 Programmatic Access

Query routes from your code using the facade or dependency injection. Each route is a typed RouteData object:

use Projecthanif\RouteScope\Facades\RouteScope;

RouteScope::all();  // Collection<int, RouteData>
RouteScope::api();  // Routes under /api or using the "api" middleware group
RouteScope::web();  // All other routes
RouteScope::filter(fn (RouteData $route) => $route->hasMiddleware('auth'));

🎨 Smart Categorization

Routes are automatically organized:

  • API Routes: Everything under /api or using the api middleware group
  • Web Routes: Your standard web application routes

⚙️ Flexible Filtering

Exclude routes you don't care about:

  • Debug tools (Telescope, Ignition)
  • Internal Laravel routes
  • Third-party package routes
  • Custom patterns you define

🔒 Type-Safe

Built with strict typing and comprehensive type hints for a better development experience with IDE autocomplete and static analysis tools.

Usage Examples

View All Routes in a Custom Command

use Projecthanif\RouteScope\Data\RouteData;
use Projecthanif\RouteScope\Facades\RouteScope;

class InspectRoutes extends Command
{
    public function handle()
    {
        foreach (RouteScope::all() as $route) {
            $this->line(sprintf('%-12s %s', implode('|', $route->methods), $route->uri));
        }
    }
}

Find API Routes Without Authentication

$unprotected = RouteScope::api()
    ->reject(fn (RouteData $route) => $route->hasMiddleware('auth') || $route->hasMiddleware('auth:sanctum'));

hasMiddleware() checks both the declared middleware and the resolved middleware (after expanding groups and aliases). It also matches parameterized middleware, so hasMiddleware('throttle') matches throttle:60,1.

Generate API Documentation

$markdown = "# API Endpoints\n\n";

foreach (RouteScope::api() as $route) {
    $markdown .= '### '.implode('|', $route->methods)." {$route->uri}\n\n";
    $markdown .= "**Controller**: `{$route->action}`\n";
    $markdown .= '**Middleware**: '.implode(', ', $route->middleware)."\n\n";
}

file_put_contents('api-docs.md', $markdown);

Export as JSON

RouteData implements JsonSerializable, so collections can be returned or encoded directly:

return response()->json(RouteScope::all());

Dependency Injection

use Projecthanif\RouteScope\Services\RouteScopeService;

class RouteAnalysisController extends Controller
{
    public function index(RouteScopeService $routeScope)
    {
        return view('admin.routes', ['routes' => $routeScope->all()]);
    }
}

Auditing Routes

routescope:audit checks your routes for common mistakes:

Rule Severity Catches
missing-action error Controller classes or methods that don't exist
overridden-route warning A route silently replaced by a later definition of the same method and URI
shadowed-route warning A route that never matches because an earlier one catches it (e.g. /users/{user} registered before /users/create)
duplicate-name warning Several routes sharing a name, so route() only reaches one
api-without-auth warning API routes without authentication middleware (signed URLs count as protected)
php artisan routescope:audit
  WARN   POST /api/v1/auth/login  api-without-auth
         API route has no authentication middleware.

  0 errors, 1 warning

It exits with a non-zero code when it finds issues, so you can run it in CI:

php artisan routescope:audit                  # fail on warnings and errors (default)
php artisan routescope:audit --fail-on=error  # fail only on errors
php artisan routescope:audit --fail-on=never  # report only
php artisan routescope:audit --json           # machine-readable output

The dashboard shows the same issues on each route, with a header button to show only affected routes.

Configuring the Audit

'audit' => [
    // Middleware that counts as authentication. "auth" also matches "auth:sanctum".
    'auth_middleware' => ['auth', 'auth.basic', 'signed', /* ... */],

    // URI patterns or route names to skip, per rule, or "*" for every rule
    'ignore' => [
        'api-without-auth' => ['api/*/auth/login', 'api/*/auth/register', 'webhooks.*'],
        '*' => ['api/internal/*'],
    ],

    // Replace or extend the rules. Each implements Projecthanif\RouteScope\Audit\Rule.
    'rules' => [
        \Projecthanif\RouteScope\Audit\Rules\MissingAction::class,
        // ...
        \App\Audit\RequireRouteNames::class,
    ],
],

A custom rule returns Issue objects and can type-hint dependencies in its constructor:

use Projecthanif\RouteScope\Audit\{Issue, Rule, Severity};
use Projecthanif\RouteScope\Services\RouteScopeService;

final class RequireRouteNames implements Rule
{
    public function __construct(private RouteScopeService $routes) {}

    public function id(): string
    {
        return 'unnamed-route';
    }

    public function check(): iterable
    {
        foreach ($this->routes->all() as $route) {
            if ($route->name === null) {
                yield new Issue($this->id(), Severity::Warning, 'Route has no name.', $route);
            }
        }
    }
}

Exporting Routes

routescope:export writes your routes as JSON, Markdown or an OpenAPI skeleton. Output is deterministic (no timestamps), so you can commit it and review route changes in diffs.

php artisan routescope:export                                   # JSON to standard output
php artisan routescope:export markdown --output=docs/routes.md  # Markdown tables
php artisan routescope:export openapi --output=openapi.json     # OpenAPI 3.1 skeleton
php artisan routescope:export json --only=api                   # api, web or all
  • json: every RouteData field for each route.
  • markdown: a table per section (API, web) with methods, URI, name, action and middleware.
  • openapi: API routes only unless you pass --only. It includes paths, operations and path parameters, and uses app.name as the title. Optional parameters ({tab?}) become separate paths, since OpenAPI has no optional path parameters. [0-9]+ constraints become integers, and other where() patterns become string patterns. Requests, responses and security can't be derived from routes, so each operation gets a placeholder response and its middleware under x-middleware for you to fill in from.

API Reference

RouteScope::all(): Collection<int, RouteData>

Returns every route, sorted by URI and then by HTTP method. RouteScope's own routes and excluded_patterns are left out. api(), web() and filter(callable) return the same collection narrowed down.

RouteData

Property Type Example
methods list<string> ['GET', 'POST'] (never HEAD/OPTIONS)
uri string /users/{user}
name ?string users.show
domain ?string {account}.example.com
action string App\Http\Controllers\UserController@show, or Closure
source string http/controllers/UserController::show, Closure, View: welcome, Redirect: /new
middleware list<string> ['web', 'auth'], as declared
resolvedMiddleware list<string> Route and controller middleware with groups and aliases expanded, in the order Laravel runs them (sorted by middleware priority)
parameters list<RouteParameter> name, optional, and pattern (from where() constraints)
file / line ?string / ?int app/Http/Controllers/UserController.php, 42 (relative to the app when inside it)
isApi bool
isFallback bool

Methods: hasMethod(string), hasMiddleware(string), key(), toArray() (snake_case keys), jsonSerialize().

RouteScope::globalMiddleware() returns the HTTP kernel's global middleware, which runs before every route's resolvedMiddleware.

RouteScope::getAllRoutes(): array (deprecated)

The v2 format: ['apiRoutes' => Collection, 'webRoutes' => Collection], with one array per HTTP method (method, path, name, source, middleware). It still works in v3 and will be removed in v4. See UPGRADE.md.

Environment Variables

# Enable/disable the package (automatically disabled in production)
ROUTESCOPE_ENABLED=true

# Customize the dashboard URL prefix
ROUTESCOPE_PREFIX=routescope

Production Safety

RouteScope is designed to be safe by default:

  1. Auto-disabled in production - The default configuration only enables RouteScope in local/development environments
  2. Gated outside local - When enabled elsewhere, the viewRouteScope gate must pass (see Authorization)
  3. Dev dependency - Install with --dev to exclude from production builds
  4. Lightweight - Zero runtime overhead when disabled
  5. No database - Purely reads from Laravel's route collection

To ensure it's disabled in production, add to .env.production:

ROUTESCOPE_ENABLED=false

Requirements

  • PHP 8.3 or higher
  • Laravel 11, 12 or 13

Use Cases

🐛 Debugging

"Why isn't my route working?" - See instantly if the route exists, what middleware is blocking it, and where it's defined.

📚 Documentation

Generate comprehensive route documentation for your team or API consumers programmatically.

👥 Onboarding

New developers can explore your application's API surface without diving into route files.

🔍 Auditing

Quickly identify which routes lack authentication, have duplicate definitions, or use deprecated middleware.

🏗️ Refactoring

When restructuring your application, see the full scope of route changes in one place.

Testing

composer test           # Run all tests
composer test:lint      # Code style checks
composer test:types     # Static analysis
composer test:unit      # Unit tests

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

Security

If you discover any security-related issues, please email iamustapha213@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see LICENSE.md for more information.

RouteScope - See your routes clearly. Debug confidently. Build faster.