Documentation Index Fetch the complete documentation index at: https://mintlify.com/tighten/ziggy/llms.txt
Use this file to discover all available pages before exploring further.
Installation
Ziggy includes a Vue plugin that makes the route() helper available throughout your Vue application—in templates, component scripts, and the Options API.
Basic Setup with @routes
If you’re using the @routes Blade directive, Ziggy’s config is available globally. Simply install the plugin:
import { createApp } from 'vue' ;
import { ZiggyVue } from 'ziggy-js' ;
import App from './App.vue' ;
createApp ( App )
. use ( ZiggyVue )
. mount ( '#app' );
Setup Without @routes
If you’re not using @routes, import and pass Ziggy’s configuration to the plugin:
import { createApp } from 'vue' ;
import { ZiggyVue } from 'ziggy-js' ;
import { Ziggy } from './ziggy.js' ; // Generated by php artisan ziggy:generate
import App from './App.vue' ;
createApp ( App )
. use ( ZiggyVue , Ziggy )
. mount ( '#app' );
Usage in Templates
Once the plugin is installed, use route() directly in your templates:
< template >
< nav >
< a : href = " route ( 'home' ) " class = "nav-link" > Home </ a >
< a : href = " route ( 'posts.index' ) " class = "nav-link" > Blog </ a >
< a : href = " route ( 'posts.show' , { post: post . id }) " class = "nav-link" >
{{ post . title }}
</ a >
</ nav >
</ template >
< script >
export default {
props: [ 'post' ] ,
} ;
</ script >
Vue 3 Composition API
The ZiggyVue plugin provides the route() function via Vue’s dependency injection system.
Using inject() with <script setup>
In Vue 3’s <script setup>, use inject() to access the route() function:
< template >
< div >
< h1 > {{ post . title }} </ h1 >
< a : href = " route ( 'posts.index' ) " class = "back-link" >
← Back to all posts
</ a >
</ div >
</ template >
< script setup >
import { inject } from 'vue' ;
import { ref } from 'vue' ;
const route = inject ( 'route' );
const props = defineProps ([ 'postId' ]);
// Use route() in your script
const fetchPost = async () => {
const response = await fetch ( route ( 'api.posts.show' , { post: props . postId }));
return response . json ();
};
</ script >
Standard Composition API
< template >
< a : href = " postUrl " class = "post-link" > View Post </ a >
</ template >
< script >
import { inject , computed } from 'vue' ;
export default {
props: [ 'post' ] ,
setup ( props ) {
const route = inject ( 'route' );
const postUrl = computed (() => {
return route ( 'posts.show' , { post: props . post . id });
});
return { postUrl };
} ,
} ;
</ script >
Vue 2 Support
ZiggyVue automatically detects Vue 2 and registers route() as a global method:
< template >
< div >
< a : href = " route ( 'posts.index' ) " > All Posts </ a >
</ div >
</ template >
< script >
export default {
mounted () {
// Access route() via this in Vue 2
console . log ( this . route ( 'posts.index' ));
} ,
} ;
</ script >
Complete Examples
Navigation Component
< template >
< header class = "site-header" >
< nav >
< router-link
v-for = " item in navigation "
: key = " item . name "
: to = " item . path "
>
{{ item . label }}
</ router-link >
</ nav >
</ header >
</ template >
< script setup >
import { inject , computed } from 'vue' ;
const route = inject ( 'route' );
const navigation = computed (() => [
{ name: 'home' , label: 'Home' , path: route ( 'home' ) },
{ name: 'about' , label: 'About' , path: route ( 'about' ) },
{ name: 'contact' , label: 'Contact' , path: route ( 'contact' ) },
]);
</ script >
< template >
< form @ submit . prevent = " handleSubmit " >
< input v-model = " post . title " type = "text" required />
< textarea v-model = " post . body " required ></ textarea >
< button type = "submit" > {{ isEditing ? 'Update' : 'Create' }} </ button >
</ form >
</ template >
< script setup >
import { inject , ref , computed } from 'vue' ;
import axios from 'axios' ;
const route = inject ( 'route' );
const props = defineProps ({
post: Object ,
});
const isEditing = computed (() => !! props . post ?. id );
const handleSubmit = async () => {
const url = isEditing . value
? route ( 'posts.update' , { post: props . post . id })
: route ( 'posts.store' );
const method = isEditing . value ? 'put' : 'post' ;
await axios [ method ]( url , props . post );
};
</ script >
Data Fetching with Composables
< template >
< div >
< div v-if = " loading " > Loading... </ div >
< div v-else-if = " error " > Error: {{ error }} </ div >
< div v-else >
< h1 > {{ post . title }} </ h1 >
< p > {{ post . body }} </ p >
</ div >
</ div >
</ template >
< script setup >
import { inject , ref , onMounted } from 'vue' ;
const route = inject ( 'route' );
const props = defineProps ([ 'postId' ]);
const post = ref ( null );
const loading = ref ( true );
const error = ref ( null );
const fetchPost = async () => {
try {
loading . value = true ;
const response = await fetch ( route ( 'api.posts.show' , { post: props . postId }));
post . value = await response . json ();
} catch ( e ) {
error . value = e . message ;
} finally {
loading . value = false ;
}
};
onMounted ( fetchPost );
</ script >
TypeScript Support
To use Ziggy with TypeScript in Vue, you need to declare the route property on Vue’s component interface.
Vue 3 TypeScript Declaration
Create a ziggy.d.ts file in your project:
// ziggy.d.ts
import { route as routeFn } from 'ziggy-js' ;
declare module 'vue' {
interface ComponentCustomProperties {
route : typeof routeFn ;
}
}
export {};
This enables TypeScript to recognize route() in your templates and Options API components without type errors.
Using with <script setup lang="ts">
< template >
< a : href = " route ( 'posts.show' , { post: props . post }) " class = "post-link" >
{{ post . title }}
</ a >
</ template >
< script setup lang = "ts" >
import { inject } from 'vue' ;
import { route as routeFn } from 'ziggy-js' ;
interface Post {
id : number ;
title : string ;
slug : string ;
}
const route = inject < typeof routeFn >( 'route' ) ! ;
const props = defineProps <{
post : Post ;
}>();
</ script >
Typed Route Parameters
For full type safety with route names and parameters, generate Ziggy’s type definitions:
php artisan ziggy:generate --types
Then your routes will have full autocomplete:
< script setup lang = "ts" >
import { inject } from 'vue' ;
import type { route as routeFn } from 'ziggy-js' ;
const route = inject < typeof routeFn >( 'route' ) ! ;
// TypeScript knows 'posts.show' exists and requires a 'post' parameter
const url = route ( 'posts.show' , { post: 1 });
</ script >
Plugin Implementation
The ZiggyVue plugin is implemented as follows:
export const ZiggyVue = {
install ( app , options ) {
const r = ( name , params , absolute , config = options ) =>
route ( name , params , absolute , config );
if ( parseInt ( app . version ) > 2 ) {
// Vue 3: Add to global properties and provide for inject()
app . config . globalProperties . route = r ;
app . provide ( 'route' , r );
} else {
// Vue 2: Add as a mixin method
app . mixin ({
methods: {
route: r ,
},
});
}
},
};
The plugin automatically passes the config you provide to .use(ZiggyVue, config) to every route() call, so you don’t need to pass it manually.
Troubleshooting
route is not defined in templates
Ensure you’ve installed the ZiggyVue plugin:
import { ZiggyVue } from 'ziggy-js' ;
app . use ( ZiggyVue );
inject() returns undefined
Make sure the plugin is installed before mounting your app, and that you’re using Vue 3.
TypeScript errors in templates
Add the module declaration for ComponentCustomProperties as shown in the TypeScript section above.
Next Steps
TypeScript Set up full type safety and autocompletion
React Use Ziggy with React instead
Route Helper Learn all route() function capabilities
JavaScript Frameworks General framework integration guide