Use your Laravel routes in JavaScript — A powerful alternative to Ziggy
Installation • Usage • Features • Frameworks • API
Pathify brings your Laravel routes to JavaScript with extras that Ziggy doesn't have:
┌─────────────────────────────────┬─────────┬─────────┐
│ Feature │ Ziggy │ Pathify │
├─────────────────────────────────┼─────────┼─────────┤
│ Route generation & parameters │ ✓ │ ✓ │
│ TypeScript support │ ✓ │ ✓ │
├─────────────────────────────────┼─────────┼─────────┤
│ Permission checking (can()) │ │ ✓ │
│ Minimal mode (reduce payload) │ │ ✓ │
│ Route caching │ │ ✓ │
│ Intelligent prefetching │ │ ✓ │
│ Auto breadcrumbs │ │ ✓ │
│ Navigation builder │ │ ✓ │
│ Multi-language URLs (i18n) │ │ ✓ │
│ Auto .gitignore management │ │ ✓ │
└─────────────────────────────────┴─────────┴─────────┘
# Install via Composer
composer require herolabid/pathify
# Publish config (optional)
php artisan vendor:publish --tag=pathify-config
# Publish JavaScript files (for Vue/React/TypeScript projects)
php artisan vendor:publish --tag=pathify-jsThis will copy JS/TS files to resources/js/vendor/pathify/.
Just add the directive — no imports needed:
<head>
@pathify
@vite(['resources/js/app.js'])
</head>// Available globally via window.Pathify
route('posts.index') // → /posts
route('posts.show', { post: 1 }) // → /posts/1After publishing JS files:
// Vue
import { useRoute } from '@/vendor/pathify/vue'
const route = useRoute()
// React
import { useRoute } from '@/vendor/pathify/react'
const route = useRoute()
// Vanilla JS
import { route } from '@/vendor/pathify/route'import { setupPathifyFromPage, createPathifyListener } from '@/vendor/pathify/inertia'
import { router } from '@inertiajs/vue3' // or @inertiajs/react
createInertiaApp({
setup({ el, App, props, plugin }) {
// Initialize BEFORE mounting
setupPathifyFromPage(props.initialPage)
// Keep in sync during navigation
router.on('navigate', createPathifyListener())
// Mount app...
},
})route('posts.index') // → /posts
route('posts.show', { post: 1 }) // → /posts/1
route('posts.show', [1]) // → /posts/1 (positional)
route('posts.index', { page: 2, sort: 'desc' }) // → /posts?page=2&sort=desc
route.current() // → 'posts.show'
route.current('posts.*') // → true
route.has('posts.index') // → true
route.params // → { post: '1' }Reduce payload by sending only routes relevant to current page:
// config/pathify.php
'minimal' => [
'enabled' => true,
'include_current' => true, // users.show includes users.*
'include_common' => true,
'common_routes' => ['home', 'login', 'logout', 'dashboard'],
'always_include' => [],
],Or via Blade directive:
{{-- Auto minimal (based on current route) --}}
@pathifyMinimal
{{-- Manual patterns --}}
@pathify(['users.*', 'roles.*', 'dashboard'])Result: If on users.edit, only sends ~10 routes instead of 50+!
route.can('admin.dashboard') // → false (requires auth)
route.can('posts.create') // → false (requires permission)// Laravel route with permission
Route::middleware(['auth', 'can:create-posts'])->group(function () {
Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
});<a v-if="route.can('posts.create')" :href="route('posts.create')">New Post</a>// config/pathify.php
'only' => ['dashboard', 'users.*', 'roles.*'],
// atau
'except' => ['admin.*', 'api.*', '_debugbar.*'],// config/pathify.php
'groups' => [
'public' => ['home', 'login', 'register'],
'admin' => ['users.*', 'roles.*'],
],@pathify('admin') {{-- Only admin routes --}}route.breadcrumbs()
// → [
// { name: 'home', label: 'Home', url: '/' },
// { name: 'posts.index', label: 'Posts', url: '/posts' },
// { name: 'posts.show', label: 'Show', url: '/posts/1' }
// ]// config/pathify.php
'navigation' => [
'main' => [
['route' => 'home', 'label' => 'Home'],
['route' => 'dashboard', 'label' => 'Dashboard', 'auth' => true],
['label' => 'Admin', 'permission' => 'admin', 'children' => [
['route' => 'admin.users', 'label' => 'Users'],
]],
],
],route.navigation('main') // Auto-filtered by user permissions// config/pathify.php
'localization' => [
'enabled' => true,
'locales' => ['en', 'id', 'es'],
'default' => 'en',
],route('posts.index', { _locale: 'id' }) // → /id/posts
route.t('posts.index', {}, 'es') // → /es/posts// config/pathify.php
'prefetch' => [
'enabled' => true,
'strategy' => 'hover', // 'hover', 'viewport', 'idle'
],// config/pathify.php
'cache' => ['enabled' => env('PATHIFY_CACHE', false), 'ttl' => 3600],php artisan pathify:clearimport { createApp } from 'vue'
import { PathifyVue } from '@/vendor/pathify/vue'
createApp(App).use(PathifyVue).mount('#app')<script setup>
import { useRoute } from '@/vendor/pathify/vue'
const route = useRoute()
</script>
<template>
<a :href="route('home')">Home</a>
<span v-if="route.current('posts.*')">Viewing posts</span>
</template>import { useRoute } from '@/vendor/pathify/react'
function Nav() {
const route = useRoute()
return <a href={route('home')}>Home</a>
}import { setupPathifyFromPage, createPathifyListener } from '@/vendor/pathify/inertia'
import { router } from '@inertiajs/vue3'
createInertiaApp({
setup({ el, App, props, plugin }) {
setupPathifyFromPage(props.initialPage)
router.on('navigate', createPathifyListener())
// ...
},
})Generate type definitions:
php artisan pathify:typesroute('posts.show', { post: 1 }) // ✓ OK
route('posts.show', {}) // ✗ Error: missing 'post'route(name, params?, absolute?) // Generate URL
route.current() // Get current route name
route.current(name, params?) // Check if matches
route.is(name, params?) // Alias for current()
route.has(name) // Check existence (supports wildcard)
route.can(name) // Check permission
route.params // Current route parameters
route.url // Base URL
route.breadcrumbs(name?, params?) // Get breadcrumbs
route.navigation(name) // Get nav items
route.t(name, params?, locale?) // Localized URL@pathify {{-- All routes --}}
@pathify('admin') {{-- Group mode --}}
@pathify(['users.*']) {{-- Minimal mode with patterns --}}
@pathifyMinimal {{-- Auto minimal mode --}}
@pathifyMinimal(['users.*']) {{-- Manual minimal mode --}}
@pathifyConfig {{-- Raw JSON config --}}php artisan pathify:generate # Generate JS config file
php artisan pathify:generate --types # With TypeScript definitions
php artisan pathify:types # TypeScript definitions only
php artisan pathify:clear # Clear route cacheGenerated files are auto-added to .gitignore.
| Problem | Solution |
|---|---|
Pathify config not found |
Add @pathify directive or call setupPathifyFromPage() |
| Routes not appearing | Add name: ->name('posts.index'), check except config |
| TypeScript errors | Run php artisan pathify:types |
| Inertia not updating | Add router.on('navigate', createPathifyListener()) |
| Permissions not working | Set include_permissions: true in config |
If you find this package helpful, consider buying me a coffee:
MIT - Built by Herolab ID