Skip to main content

Introduction to Ziggy

Ziggy is a Laravel package that makes your named routes available in JavaScript, providing a familiar route() helper function that mirrors Laravel’s PHP API.

What is Ziggy?

Ziggy bridges the gap between your Laravel backend and JavaScript frontend by automatically exposing your application’s named routes to JavaScript. Instead of hardcoding URLs in your JavaScript code, you can use the same convenient route() helper you’re familiar with from Laravel.
// In your Laravel routes
Route::get('posts/{post}', [PostController::class, 'show'])->name('posts.show');
// In your JavaScript
route('posts.show', 1); // 'https://ziggy.test/posts/1'

Why Use Ziggy?

Type-Safe Routes

Catch broken route references at development time instead of runtime. Ziggy includes TypeScript support with route name and parameter autocompletion.

DRY Principle

Define your routes once in Laravel and use them everywhere. No need to maintain duplicate route definitions in JavaScript.

Automatic Updates

When you change a route in Laravel, your JavaScript automatically gets the update. No manual synchronization required.

Framework Agnostic

Works seamlessly with Vue, React, or vanilla JavaScript. Includes dedicated plugins and hooks for popular frameworks.

Key Features

Route Parameters

Ziggy handles all types of route parameters, from simple to complex:
// Single parameter
route('posts.show', 1); // '/posts/1'

// Multiple parameters
route('venues.events.show', [1, 2]); // '/venues/1/events/2'
route('venues.events.show', { venue: 1, event: 2 }); // '/venues/1/events/2'

// Query parameters
route('posts.index', { page: 5, sort: 'title' }); // '/posts?page=5&sort=title'

Route Model Binding

Ziggy understands Laravel’s route model binding and automatically uses the correct key:
const post = {
    id: 3,
    slug: 'introducing-ziggy',
    title: 'Introducing Ziggy v1'
};

// Ziggy knows to use 'slug' if that's your route key
route('posts.show', post); // '/posts/introducing-ziggy'

Current Route Detection

Check which route you’re currently on:
route().current(); // 'events.index'
route().current('events.index'); // true
route().current('events.*'); // true
route().current('events.show'); // false

// With parameter checking
route().current('venues.show', { venue: 1 }); // true only if venue is 1

Route Parameter Access

Access parameters from the current URL:
// At URL: https://tighten.ziggy.dev/posts/4?lang=en
route().params; // { team: 'tighten', post: '4', lang: 'en' }

Comparison with Alternatives

Without Ziggy:
axios.get(`/posts/${postId}/comments`)
Problem: Routes break when URLs change, no validation, easy to make typosWith Ziggy:
axios.get(route('posts.comments.index', { post: postId }))
Benefit: Type-safe, validated, updates automatically
Without Ziggy: Maintain a separate routes.js file that duplicates your Laravel routesProblem: Double maintenance, routes get out of sync, manual updates requiredWith Ziggy: Routes are automatically generated from your Laravel applicationBenefit: Single source of truth, zero maintenance
Without Ziggy: Pass individual URLs from Blade to JavaScriptProblem: Requires passing every URL you need, clutters templatesWith Ziggy: All routes available via single @routes directiveBenefit: Clean templates, all routes available everywhere

How It Works

Ziggy works in three simple steps:
1

Define Routes in Laravel

Write your routes normally in Laravel with named routes:
Route::get('posts/{post}', [PostController::class, 'show'])->name('posts.show');
2

Add @routes Directive

Include Ziggy’s Blade directive in your layout:
@routes
This makes all your routes available to JavaScript.
3

Use route() in JavaScript

Call the route() helper anywhere in your JavaScript:
const url = route('posts.show', { post: 123 });

Security Considerations

By default, the @routes directive includes all your application’s named routes in the page HTML, which can be viewed by end users.
Ziggy includes powerful filtering options to control which routes are exposed:
  • Route filtering: Use only and except in your config
  • Route groups: Define groups of routes for different pages
  • Per-page control: Pass group names to @routes directive
// config/ziggy.php
return [
    'except' => ['admin.*', 'api.internal.*'],
];
Filtering routes in Ziggy is not a security feature. Always protect sensitive routes with proper authentication and authorization, regardless of whether they appear in Ziggy’s output.

Getting Started

Ready to start using Ziggy? Follow the installation guide to get set up in minutes.

Installation

Install Ziggy and add the @routes directive to your application

Build docs developers (and LLMs) love