@routes Blade directive is the simplest way to make your Laravel routes available to JavaScript. It outputs a <script> tag containing both your route configuration and Ziggy’s route() helper function.
Basic Usage
Add the@routes directive to your main layout, before your application’s JavaScript:
app.blade.php
route() function available globally in your JavaScript.
Generated Output
The@routes directive generates a script tag like this:
Directive Options
The@routes directive accepts several optional parameters:
Group Parameter
Pass a group name to only include routes from that group:config/ziggy.php:
config/ziggy.php
Multiple Groups
Pass an array to include routes from multiple groups:Nonce Parameter
Add a Content Security Policy nonce to the script tag:<script> tag:
JSON Parameter
Output routes as JSON instead of JavaScript:When using
json: true, the route() function is not included. You’ll need to load it separately from the NPM package or vendor directory.Parameter Combinations
You can combine parameters using named arguments:Configuration Options
Customize the@routes directive behavior in config/ziggy.php.
Skip Route Function
If you only want to output the Ziggy config (not theroute() function), set:
config/ziggy.php
route() function separately:
Custom Output Classes
You can customize how Ziggy generates its output by specifying custom output classes:config/ziggy.php
Stringable interface.
Multiple @routes Directives
If you use@routes multiple times on the same page, only the first call includes the full route() function. Subsequent calls output a merge script that adds additional routes:
Security Considerations
What Information is Exposed?
- Route names (e.g.,
posts.show,admin.users.index) - Route URIs (e.g.,
/posts/{post},/admin/users) - Route parameters (e.g.,
['post']) - HTTP methods (e.g.,
['GET', 'HEAD']) - Route bindings (e.g.,
{ post: 'slug' }) - Domain constraints (if any)
- Middleware (if
ziggy.middlewareis enabled)
What is NOT Exposed?
- Route closures or controller logic
- Authentication/authorization rules
- Validation rules
- Any actual data or database records
Best Practices
- Filter sensitive routes: Use the
exceptconfig to hide admin or internal routes on public pages - Use route groups: Only expose relevant routes on each page using groups
- Protect routes with middleware: Always use Laravel’s authentication and authorization
- Obfuscation is not security: Don’t rely on hiding routes as a security measure
Performance Considerations
The@routes directive generates route configuration on every page load. For large applications with many routes, consider:
- Filtering routes: Only include routes you actually need using groups or filters
- Caching: Use Laravel’s view caching (
php artisan view:cache) - Route caching: Use Laravel’s route caching (
php artisan route:cache) - Using ziggy:generate: For SPAs, generate a static file instead of using
@routes
Can I use @routes in components instead of layouts?
Can I use @routes in components instead of layouts?
Yes, you can use
@routes in Blade components. However, be careful not to include it multiple times on the same page, as this will output multiple script tags.If you need to use @routes in a component that might be included multiple times, consider:- Using a layout file instead
- Using
@onceto ensure it only outputs once - Checking if routes have been output already
What's the difference between @routes and ziggy:generate?
What's the difference between @routes and ziggy:generate?
- @routes: Embeds routes in HTML on every page load, perfect for traditional Blade apps
- ziggy:generate: Creates a static JavaScript file, better for JavaScript frameworks and SPAs
@routes when:- Building traditional server-rendered Laravel apps
- You want different routes on different pages
- You don’t use a JavaScript build tool
ziggy:generate when:- Building SPAs with Vue, React, etc.
- Using a JavaScript build tool (Vite, Webpack)
- You want to import routes as an ES module
How does the merge script work?
How does the merge script work?
When you call
@routes multiple times, the BladeRouteGenerator class tracks whether it has already generated output using a static property $generated (src/BladeRouteGenerator.php:11).- First call: Sets
$generated = trueand outputs the full script with theroute()function - Subsequent calls: Generate a merge script that uses
Object.assign()to add routes to the existingZiggy.routesobject
route() function code.Can I pass dynamic values to @routes?
Can I pass dynamic values to @routes?
Yes, you can pass dynamic values using Blade syntax:This is useful for conditionally loading different route groups based on user properties.
Next Steps
CSP Configuration
Configure Content Security Policy with nonces and JSON mode
Route Groups
Organize routes into groups for different pages