Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Routes Laravel Package

bluedragon/laravel-routes

A Laravel package for working with your application's routes, offering a simple way to inspect and manage route definitions within your Laravel projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the wiring first. The package is not widely adopted, so verify what it actually registers before writing any application code:

composer require bluedragon/laravel-routes
php artisan vendor:publish --provider="BlueDragon\LaravelRoutes\RoutesServiceProvider"

If the provider name differs, find it via composer show bluedragon/laravel-routes and read vendor/bluedragon/laravel-routes/composer.json — look for extra.laravel.providers (auto-discovery) and extra.laravel.aliases. If neither exists, you must register the provider manually in bootstrap/providers.php (Laravel 11+) or config/app.php.

Three files to read before anything else:

  1. The service provider — this tells you how routes reach the browser (Blade directive, a published JS/JSON asset, or an HTTP endpoint that serves the route list).
  2. config/routes.php (or whatever the published config is named) — the filtering/whitelist options live here.
  3. resources/js/ or dist/ in the package — the client-side helper's signature. Most packages in this space mimic Ziggy's route('name', params), but confirm the arity and argument order yourself; do not assume.

First use case — the 15-minute smoke test. Add one named route, render it in a Blade view, and confirm the JS helper resolves it:

// routes/web.php
Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show');
{{-- resources/views/welcome.blade.php --}}
@routes  {{-- or whatever directive/script tag the provider exposes --}}
<script>
  console.log(route('users.show', { user: 1 }));
  // expect: /users/1
</script>

Open the browser, check the console and the page source. If the route data is emitted inline, you should see a JSON blob in the HTML. If it's a published asset, check public/js/ or public/vendor/. Knowing which of these two architectures you're dealing with determines every downstream decision.


Implementation Patterns

Baseline: emit once, globally. Put the directive in your single layout (resources/views/layouts/app.blade.php) rather than per-page, so the helper is always available. Emitting it repeatedly wastes bytes and can cause double-registration warnings.

Inertia / SPA setups. Don't rely on a Blade directive inside an Inertia app — the root app.blade.php is the only Blade file that renders. Either keep the directive there, or drop the package's helper and share the route list through HandleInertiaRequests::share() so it's available as a prop:

public function share(Request $request): array
{
    return array_merge(parent::share($request), [
        'routes' => /* package's route-collection method */,
    ]);
}

This is worth doing anyway if you need per-user route visibility (see filtering below).

Parameter binding. The common failure mode is passing a model object where the helper expects an identifier. In JavaScript you don't have Eloquent, so always pass the bound key explicitly:

route('users.show', { user: user.id })          // correct
route('users.show', user)                       // usually wrong
route('posts.show', { post: post.slug })        // when getRouteKeyName() is 'slug'

Mirror Laravel's semantics: positional arrays for required params in order, objects for named params, and extra keys become the query string. Test the query-string case explicitly — it's the behavior most commonly broken or unimplemented in smaller packages.

Alpine and Livewire. The helper is a plain global, so it works inside x-data blocks without ceremony:

<a :href="route('users.show', { user: {{ $user->id }} })">View</a>

For Livewire, prefer wire:navigate with server-rendered route() calls. The JS helper earns its keep on client-side redirects and fetch() targets, not on static links.

Filtering is mandatory, not optional. A route-list dump on a real app is 40–120 KB of JSON and includes admin panels, debug endpoints, and internal APIs. Configure a whitelist of route-name prefixes (web., public.) or an explicit include list, and confirm the output size after filtering. Anything reachable by an unauthenticated browser is effectively public documentation of your attack surface.

Deployment ordering. Whatever generates the JS/JSON must run after php artisan route:cache and after config is cached, and the resulting asset must be part of your build artifact. In practice:

"scripts": {
  "post-autoload-dump": [
    "@php artisan route:clear",
    "@php artisan vendor:publish --tag=routes-assets --force"
  ]
}

Skip this and you ship stale routes to production the first time someone renames an endpoint. Add a CI check that diffs the generated asset against the committed one.

Testing. Assert the generated output, not the helper. A cheap regression test:

it('exposes public routes only', function () {
    $payload = $this->get('/')->getContent(); // or call the provider's generator directly
    expect($payload)->toContain('users.show')
                   ->not->toContain('admin.dashboard');
});

That single test catches filtering regressions, route:cache interactions, and accidental exposure — the three things that actually break.


Gotchas and Tips

This is a near-zero-adoption package. Zero stars, zero dependents, no ecosystem. Treat it as a small internal utility rather than infrastructure: pin the exact version in composer.json, vendor-audit the source (it's small — read it all, it will take ten minutes), and have an exit plan. Ziggy is the de facto standard for this exact problem, is maintained, and has framework adapters for Vue/React/Svelte. If you hit more than one limitation in the list below, switch rather than patch — the migration is a route() call signature and a directive name.

Route model binding silently diverges. route('posts.show', $post) on the PHP side uses getRouteKeyName(). The JS helper has no idea about that method. Any route with a custom key (slug, UUID, hashid) will produce a URL that 404s in the browser but works in Blade. Grep your route list for models overriding getRouteKeyName() and handle them explicitly.

Signed URLs are not portable. URL::temporarySignedRoute() and URL::signedRoute() are server-only — the signature is an HMAC over the full URL with a secret the client doesn't have. No JS route package can generate these. Fetch the signed URL from an endpoint and use it directly.

Domain and subdomain routes bake in the wrong host. If a route is defined with ->domain('{tenant}.example.com'), the generated URL depends on the current request host at generation time. Cached or published assets will pin the first host they saw. Regenerate per-request, or exclude these routes and construct them manually.

Localized routes break on locale switch. Route::localized() / app()->getLocale() affects generation. If you serve multiple locales, the route list must be regenerated after a locale change — a static asset won't do it. For SPA locale switching, exclude localized route groups from the asset and generate URLs server-side.

route:cache interaction. If the package reads routes at boot via the router's collection, make sure it works when routes are cached (the collection is deserialized, not re-registered). Symptom: helper returns undefined in production but works in local dev. Test with php artisan optimize before every deploy.

Escaping and JSON encoding. Route parameters containing quotes, <, /, or & are a common source of broken output or XSS. When the package inlines JSON into a <script> tag, it must use json_encode(..., JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) or Js::from(). Inspect the raw HTML output with a parameter like O'Brien & Sons <script> and confirm it doesn't break the page. If it does, that's a security issue worth reporting and working around.

Debugging checklist, in order:

  1. php artisan route:list --json | jq '.[].name' — confirm the route name exists and is spelled exactly as in JS.
  2. View source, not the console — is the JSON actually present in the HTML?
  3. php artisan config:clear && php artisan route:clear — the two caches that cause ~90% of "stale route" reports.
  4. Check load order — the helper must be defined before any script calling it. Deferred/async script tags are a classic culprit.
  5. Confirm the helper isn't being shadowed by another global named route (Laravel Mix/Vite plugins, analytics snippets).

Extension points worth knowing. Most packages like this expose the generation step as a callable or an event (RouteListGenerated-style). If yours does, hook it to append app-specific routes that aren't in Laravel's router (feature-flagged frontend routes, third-party links) rather than editing the published asset. Never edit published assets directly — --force re-publishes will destroy your changes on the next deploy.

When to walk away. If you need any of: signed URLs, per-user route filtering, TypeScript types for route names, or multi-domain support — evaluate Ziggy or tightenco/ziggy's TypeScript generation first. Those are the four requirements that most frequently force a rewrite, and this package's zero-dependency-base means you'll be maintaining the fork yourself.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin