PHPackages                             sysmatter/laravel-navigation - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. sysmatter/laravel-navigation

Abandoned → [offload-project/laravel-navigation](/?search=offload-project%2Flaravel-navigation)Library[Utility &amp; Helpers](/categories/utility)

sysmatter/laravel-navigation
============================

Configurable navigation package for Laravel with breadcrumbs and tree generation

v2.0.0(5mo ago)0363↓50%1MITPHPCI passing

Since Oct 5Pushed 5mo agoCompare

[ Source](https://github.com/sysmatter/laravel-navigation)[ Packagist](https://packagist.org/packages/sysmatter/laravel-navigation)[ Docs](https://github.com/sysmatter/laravel-navigation)[ RSS](/packages/sysmatter-laravel-navigation/feed)WikiDiscussions main Synced 2mo ago

READMEChangelog (10)Dependencies (11)Versions (22)Used By (0)

Laravel Navigation Packaged Moved -&gt; [offload-project/laravel-navigation](https://github.com/offload-project/laravel-navigation)
===================================================================================================================================

[](#laravel-navigation-packaged-moved---offload-projectlaravel-navigation)

A powerful, flexible navigation management package for Laravel applications. Define multiple navigation structures with breadcrumbs, active state detection, and pre-compiled icons - perfect for React, Inertia.js, and traditional Blade applications.

Features
--------

[](#features)

- 🗺️ **Multiple Navigations** - Define unlimited navigation structures (main nav, footer, sidebars, etc.)
- 🔗 **Route-Based** - Use Laravel route names with full IDE autocomplete support
- 🍞 **Breadcrumb Generation** - Automatically generate breadcrumbs from your navigation structure
- 🌳 **Tree Export** - Export navigation as nested JSON for frontend frameworks
- ✨ **Active State Detection** - Smart detection of active menu items and their parents
- 🎨 **Pre-compiled Icons** - Compile Lucide icons to SVG strings for optimal performance
- 🔘 **Action Support** - Define POST/DELETE actions (logout, form submissions, etc.)
- 🌐 **External URLs** - Mix internal routes with external links
- ✅ **Validation** - Artisan command to validate all route references
- 🧪 **Fully Tested** - Comprehensive Pest test suite

Installation
------------

[](#installation)

Install via Composer:

```
composer require sysmatter/laravel-navigation
```

Publish the configuration file:

```
php artisan vendor:publish --tag=navigation-config
```

Configuration
-------------

[](#configuration)

Define your navigations in `config/navigation.php`:

```
return [
    'navigations' => [
        'main' => [
            [
                'label' => 'Dashboard',
                'route' => 'dashboard',
                'icon' => 'home',
            ],
            [
                'label' => 'Users',
                'route' => 'users.index',
                'icon' => 'users',
                'can' => 'view-users',  // Only show if user has permission
                'children' => [
                    ['label' => 'All Users', 'route' => 'users.index'],
                    ['label' => 'Roles', 'route' => 'users.roles.index', 'can' => 'manage-roles'],
                    ['label' => 'Permissions', 'route' => 'users.permissions.index', 'can' => 'manage-permissions'],
                ],
            ],
            [
                'label' => 'Settings',
                'route' => 'settings.index',
                'icon' => 'settings',
                'visible' => fn() => auth()->user()?->isAdmin(),  // Dynamic visibility
            ],
        ],

        'user_menu' => [
            ['label' => 'Profile', 'route' => 'profile.edit', 'icon' => 'user'],
            ['label' => 'Settings', 'route' => 'settings.index', 'icon' => 'settings'],
            ['label' => 'Logout', 'route' => 'logout', 'method' => 'post', 'icon' => 'log-out'],
        ],

        'footer' => [
            ['label' => 'Documentation', 'url' => 'https://docs.example.com'],
            ['label' => 'Privacy Policy', 'route' => 'legal.privacy'],
            ['label' => 'Terms of Service', 'route' => 'legal.terms'],
        ],
    ],

    'icons' => [
        'compiled_path' => storage_path('navigation/icons.php'),
    ],
];
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

Get a navigation tree for your frontend:

```
use SysMatter\Navigation\Facades\Navigation;

// Get navigation tree
$mainNav = Navigation::get('main')->toTree();

// Pass to Inertia
return inertia('Dashboard', [
    'navigation' => $mainNav,
]);

// Or return as JSON
return response()->json([
    'navigation' => $mainNav,
]);
```

### With Route Parameters

[](#with-route-parameters)

For routes that require parameters:

```
// Route: /users/{user}/posts
$navigation = Navigation::get('sidebar')->toTree([
    'user' => $user->id,
]);
```

### Wildcard Parameters

[](#wildcard-parameters)

#### Overview

[](#overview)

Wildcard parameters allow you to include CRUD detail/edit pages in breadcrumbs and active states without cluttering your navigation menu. This is particularly useful for pages like `/users/123/edit` that should show breadcrumbs and mark parent items as active, but shouldn't appear in the navigation itself.

#### Basic Usage

[](#basic-usage-1)

##### Breadcrumb-Only Items

[](#breadcrumb-only-items)

Use `breadcrumbOnly: true` to hide items from navigation while keeping them in breadcrumbs:

```
'navigations' => [
    'main' => [
        [
            'label' => 'Users',
            'route' => 'users.index',
            'icon' => 'users',
            'children' => [
                [
                    'label' => 'Edit User',
                    'route' => 'users.edit',
                    'breadcrumbOnly' => true,
                    'params' => ['user' => '*'],
                ],
            ],
        ],
    ],
],
```

When visiting `/users/5/edit`:

- **Navigation**: Only shows "Users" link
- **Breadcrumbs**: Shows "Users &gt; Edit User"
- **Active State**: "Users" is marked as active

#### Wildcard Syntax

[](#wildcard-syntax)

##### Single Wildcard Parameter

[](#single-wildcard-parameter)

The `'*'` wildcard matches any parameter value:

```
[
    'label' => 'View Order',
    'route' => 'orders.show',
    'breadcrumbOnly' => true,
    'params' => ['order' => '*'],
]
```

Matches:

- `/orders/1` ✓
- `/orders/999` ✓
- `/orders/abc-123` ✓

##### Multiple Wildcard Parameters

[](#multiple-wildcard-parameters)

```
[
    'label' => 'Edit Team Member',
    'route' => 'organizations.teams.members.edit',
    'breadcrumbOnly' => true,
    'params' => [
        'organization' => '*',
        'team' => '*',
        'member' => '*',
    ],
]
```

##### Mixed Wildcard and Exact Parameters

[](#mixed-wildcard-and-exact-parameters)

Combine wildcards with exact values to match specific scenarios:

```
[
    'label' => 'Edit Admin User',
    'route' => 'organizations.users.edit',
    'breadcrumbOnly' => true,
    'params' => [
        'organization' => 5, // Only match organization 5
        'user' => '*',       // Any user
    ],
]
```

Matches:

- `/organizations/5/users/10/edit` ✓
- `/organizations/5/users/99/edit` ✓
- `/organizations/3/users/10/edit` ✗

#### Dynamic Labels

[](#dynamic-labels)

##### Single Model Instance

[](#single-model-instance)

Use closures to create dynamic labels based on route model binding:

```
[
    'label' => fn($user) => "Edit: {$user->name}",
    'route' => 'users.edit',
    'breadcrumbOnly' => true,
    'params' => ['user' => '*'],
]
```

Result: "Users &gt; Edit: John Doe"

##### Multiple Models

[](#multiple-models)

When multiple models are present, the closure receives all parameters:

```
[
    'label' => fn($params) => "Edit {$params['user']->name} in {$params['organization']->name}",
    'route' => 'organizations.users.edit',
    'breadcrumbOnly' => true,
    'params' => [
        'organization' => '*',
        'user' => '*',
    ],
]
```

Result: "Organizations &gt; Users &gt; Edit Jane Smith in Acme Corp"

##### Static Labels

[](#static-labels)

You can also use simple strings for labels:

```
[
    'label' => 'Edit User',
    'route' => 'users.edit',
    'breadcrumbOnly' => true,
    'params' => ['user' => '*'],
]
```

Result: "Users &gt; Edit User"

#### Active State

[](#active-state)

##### Automatic Bubbling

[](#automatic-bubbling)

Active state automatically bubbles up through the navigation hierarchy:

```
[
    'label' => 'Admin',
    'route' => 'admin.dashboard',
    'children' => [
        [
            'label' => 'Users',
            'route' => 'admin.users.index',
            'children' => [
                [
                    'label' => 'Edit User',
                    'route' => 'admin.users.edit',
                    'breadcrumbOnly' => true,
                    'params' => ['user' => '*'],
                ],
            ],
        ],
    ],
]
```

When on `/admin/users/5/edit`:

- "Admin" is active ✓
- "Users" is active ✓
- "Edit User" is in breadcrumbs but not in nav

#### Common Patterns

[](#common-patterns)

##### CRUD Resources

[](#crud-resources)

```
[
    'label' => 'Products',
    'route' => 'products.index',
    'icon' => 'package',
    'children' => [
        [
            'label' => 'Create Product',
            'route' => 'products.create',
            'breadcrumbOnly' => true,
        ],
        [
            'label' => fn($product) => $product->name,
            'route' => 'products.show',
            'breadcrumbOnly' => true,
            'params' => ['product' => '*'],
        ],
        [
            'label' => fn($product) => "Edit: {$product->name}",
            'route' => 'products.edit',
            'breadcrumbOnly' => true,
            'params' => ['product' => '*'],
        ],
    ],
]
```

##### Nested Resources

[](#nested-resources)

```
[
    'label' => 'Organizations',
    'route' => 'organizations.index',
    'children' => [
        [
            'label' => fn($org) => $org->name,
            'route' => 'organizations.show',
            'breadcrumbOnly' => true,
            'params' => ['organization' => '*'],
            'children' => [
                [
                    'label' => 'Team Members',
                    'route' => 'organizations.members.index',
                    'params' => ['organization' => '*'],
                ],
                [
                    'label' => fn($params) => "Edit {$params['member']->name}",
                    'route' => 'organizations.members.edit',
                    'breadcrumbOnly' => true,
                    'params' => [
                        'organization' => '*',
                        'member' => '*',
                    ],
                ],
            ],
        ],
    ],
]
```

#### Parameters Without Wildcards

[](#parameters-without-wildcards)

You can also pass regular parameters for URL generation:

```
// Generate navigation with specific params
$tree = Navigation::get('main')->toTree(['filter' => 'active']);

// Generate breadcrumbs with params
$breadcrumbs = Navigation::breadcrumbs('main', 'users.edit', ['user' => 5]);
```

#### Tips

[](#tips)

1. **Model Requirements**: When using dynamic labels with models, ensure your models implement `getRouteKey()` or `__toString()` for proper URL generation.
2. **Performance**: Wildcard matching happens at runtime, so it's performant even with many breadcrumb-only items.
3. **Specificity**: More specific routes should come before more general ones in your navigation config.
4. **Navigation vs Breadcrumbs**: Use `breadcrumbOnly` for detail/edit pages, and `navOnly` (if needed) for items that should only appear in navigation but not breadcrumbs.

#### Frontend Integration

[](#frontend-integration)

When building your React/TypeScript components, breadcrumb-only items won't appear in the navigation tree but will be present in breadcrumbs:

```
// Navigation returns only visible items
const navTree = await fetch('/api/navigation/main');
// Items with breadcrumbOnly are excluded

// Breadcrumbs include breadcrumb-only items
const breadcrumbs = await fetch('/api/breadcrumbs');
// [
//   { label: 'Users', url: '/users' },
//   { label: 'Edit: John Doe', url: '/users/5/edit' }
// ]
```

### Breadcrumbs

[](#breadcrumbs)

Generate breadcrumbs from the current route:

```
// Auto-detect current route
$breadcrumbs = Navigation::breadcrumbs();

// Specify nav tree to find current route in
$breadcrumbs = Navigation::breadcrumbs('main');

// Or specify a route
$breadcrumbs = Navigation::breadcrumbs('main', 'users.show');

// With parameters
$breadcrumbs = Navigation::breadcrumbs('main', 'users.show', [
    'user' => $user->id,
]);
```

### Output Format

[](#output-format)

The `toTree()` method returns an array structure perfect for frontend consumption:

```
[
    [
        'id' => 'nav-main-0',
        'label' => 'Dashboard',
        'url' => 'http://localhost/dashboard',
        'isActive' => true,
        'icon' => '...',  // Compiled SVG (if icons compiled)
        'children' => [],
    ],
    [
        'id' => 'nav-main-1',
        'label' => 'Users',
        'url' => 'http://localhost/users',
        'isActive' => false,
        'icon' => '...',
        'children' => [
            [
                'id' => 'nav-main-1-0',
                'label' => 'All Users',
                'url' => 'http://localhost/users',
                'isActive' => false,
                'children' => [],
            ],
            // ...
        ],
    ],
    [
        'id' => 'nav-main-2',
        'label' => 'Logout',
        'url' => 'http://localhost/logout',
        'method' => 'post',  // Only present when specified
        'isActive' => false,
        'icon' => '...',
        'children' => [],
    ],
]
```

Frontend Integration
--------------------

[](#frontend-integration-1)

### React + Inertia.js

[](#react--inertiajs)

```
import {Link} from '@inertiajs/react';

interface NavigationItem {
    id: string;
    type: 'link' | 'section' | 'separator';
    label?: string;
    url?: string;
    method?: string;
    isActive?: boolean;
    icon?: string;
    children?: NavigationItem[];
}

export default function Navigation({items}: { items: NavigationItem[] }) {
    return (

            {items.map((item) => (

                    {item.method ? (

                            {item.icon && (

                            )}
                            {item.label}

                    ) : (

                            {item.icon && (

                            )}
                            {item.label}

                    )}

                    {item.children.length > 0 && (

                    )}

            ))}

    );
}
```

### TypeScript + React

[](#typescript--react)

```
// Pass from Laravel
const Page = ({navigation}: { navigation: NavigationItem[] }) => {
    return ;
};
```

### Breadcrumbs Component

[](#breadcrumbs-component)

```
import {Link} from '@inertiajs/react';

interface Breadcrumb {
    label: string;
    url: string;
    route: string;
}

export default function Breadcrumbs({items}: { items: Breadcrumb[] }) {
    return (

                {items.map((item, index) => (

                        {index > 0 && /}
                        {index === items.length - 1 ? (
                            {item.label}
                        ) : (

                                {item.label}

                        )}

                ))}

    );
}
```

Icon Compilation
----------------

[](#icon-compilation)

For optimal performance, compile Lucide icons to SVG strings instead of using the DynamicIcon component:

```
php artisan navigation:compile-icons
```

This command:

1. Extracts all icon names from your navigation config
2. Downloads SVG files from the Lucide CDN
3. Saves them as PHP arrays in `storage/navigation/icons.php`
4. Automatically includes them in your navigation output

**Benefits:**

- ✅ No runtime overhead
- ✅ No client-side icon loading
- ✅ Smaller bundle size
- ✅ Faster page loads

Add to your deployment process:

```
php artisan navigation:compile-icons
```

Route Validation
----------------

[](#route-validation)

Ensure all route names in your navigation config exist:

```
php artisan navigation:validate
```

Output:

```
Validating navigation: main
Validating navigation: user_menu
Validating navigation: footer
✓ All navigation routes are valid!

```

Or if there are errors:

```
Validating navigation: main
✗ Found 1 invalid route(s):
  - main: Route 'users.invalid' not found (at: Users > Invalid Link)

```

**Add to CI/CD:**

```
# .github/workflows/tests.yml
-   name: Validate Navigation
    run: php artisan navigation:validate
```

Advanced Features
-----------------

[](#advanced-features)

### Custom Attributes

[](#custom-attributes)

Add any custom data to navigation items:

```
'navigations' => [
    'main' => [
        [
            'label' => 'Notifications',
            'route' => 'notifications.index',
            'badge' => '5',           // Custom attribute
            'badgeColor' => 'red',    // Custom attribute
            'requiresPro' => true,    // Custom attribute
        ],
    ],
],
```

These will be included in the output:

```
[
    'label' => 'Notifications',
    'url' => 'http://localhost/notifications',
    'badge' => '5',
    'badgeColor' => 'red',
    'requiresPro' => true,
    // ...
]
```

### Conditional Visibility

[](#conditional-visibility)

Control which navigation items are visible based on permissions, authentication, or custom logic.

#### Using `visible` Attribute

[](#using-visible-attribute)

Show/hide items with boolean values or callables:

```
'navigations' => [
    'main' => [
        // Static boolean
        [
            'label' => 'Beta Features',
            'route' => 'beta.index',
            'visible' => config('app.beta_enabled'),
        ],

        // Dynamic callable
        [
            'label' => 'Admin Panel',
            'route' => 'admin.index',
            'visible' => fn() => auth()->user()?->isAdmin(),
        ],

        // Complex logic
        [
            'label' => 'Premium Features',
            'route' => 'premium.index',
            'visible' => fn() => auth()->check() && auth()->user()->hasActiveSubscription(),
        ],
    ],
],
```

#### Using `can` Attribute (Authorization)

[](#using-can-attribute-authorization)

Leverage Laravel's authorization gates and policies:

```
'navigations' => [
    'main' => [
        // Simple gate check
        [
            'label' => 'Users',
            'route' => 'users.index',
            'can' => 'view-users',
        ],

        // Policy with model
        [
            'label' => 'Edit Post',
            'route' => 'posts.edit',
            'can' => ['update', $post],  // Checks: $user->can('update', $post)
        ],

        // Children inherit permissions
        [
            'label' => 'Admin',
            'route' => 'admin.index',
            'can' => 'access-admin',
            'children' => [
                ['label' => 'Users', 'route' => 'admin.users', 'can' => 'manage-users'],
                ['label' => 'Settings', 'route' => 'admin.settings'],
            ],
        ],
    ],
],
```

#### Combining Conditions

[](#combining-conditions)

Use both `visible` and `can` together:

```
[
    'label' => 'Billing',
    'route' => 'billing.index',
    'visible' => fn() => config('features.billing_enabled'),
    'can' => 'view-billing',
]
```

#### Conditional Children

[](#conditional-children)

Filter child items independently:

```
[
    'label' => 'Reports',
    'route' => 'reports.index',
    'children' => [
        [
            'label' => 'Sales Report',
            'route' => 'reports.sales',
            'can' => 'view-sales',
        ],
        [
            'label' => 'Financial Report',
            'route' => 'reports.financial',
            'can' => 'view-financials',
        ],
        [
            'label' => 'Admin Report',
            'route' => 'reports.admin',
            'visible' => fn() => auth()->user()?->isAdmin(),
        ],
    ],
]
```

**Note:** If a parent has no visible children, the parent is still shown. If you want to hide the parent when all children are hidden, add a `visible` check to the parent too.

#### Define Gates in AuthServiceProvider

[](#define-gates-in-authserviceprovider)

```
// app/Providers/AuthServiceProvider.php
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('view-users', function ($user) {
        return $user->hasPermission('view-users');
    });

    Gate::define('access-admin', function ($user) {
        return $user->isAdmin();
    });
}
```

#### Benefits

[](#benefits)

✅ **Security** - Items requiring permissions won't appear in navigation
✅ **Clean UI** - Users only see what they can access
✅ **DRY** - Reuse existing gates and policies
✅ **Flexible** - Mix static config with dynamic logic
✅ **Type Safe** - All authorization goes through Laravel's auth system

### Active State Detection

[](#active-state-detection)

The package intelligently detects active states:

- **Exact match**: If the current route is `users.index`, that item is active
- **Parent match**: If current route is `users.show`, the parent `users.index` is also marked active
- **Child match**: If current route is `users.roles.index`, both `Users` parent and `Roles` child are active

### External URLs

[](#external-urls)

Mix internal routes with external links:

```
[
    'label' => 'API Docs',
    'url' => 'https://api.example.com/docs',
    'icon' => 'book-open',
],
```

### Action Items

[](#action-items)

Define items that trigger POST/DELETE requests:

```
[
    'label' => 'Logout',
    'route' => 'logout',
    'method' => 'post',
    'icon' => 'log-out',
],
```

### Sections and Separators

[](#sections-and-separators)

Organize your navigation with visual sections (containers) and dividers:

```
'navigations' => [
    'main' => [
        ['label' => 'Dashboard', 'route' => 'dashboard', 'icon' => 'home'],

        // Section container with grouped items
        [
            'label' => 'Management',
            'type' => 'section',
            'children' => [
                ['label' => 'Users', 'route' => 'users.index', 'icon' => 'users'],
                ['label' => 'Teams', 'route' => 'teams.index', 'icon' => 'users-2'],
            ],
        ],

        // Visual separator
        ['type' => 'separator'],

        ['label' => 'Settings', 'route' => 'settings.index', 'icon' => 'settings'],
        ['label' => 'Logout', 'route' => 'logout', 'method' => 'post', 'icon' => 'log-out'],
    ],
],
```

**Section Features:**

- **Container Structure**: Sections contain their children, making boundaries clear
- **Permission Control**: Apply `can` or `visible` to entire section to hide all children
- **Nested Sections**: Sections can contain other sections
- **Auto-hiding**: Sections with no visible children are automatically excluded
- **Breadcrumb Exclusion**: Sections don't appear in breadcrumbs, only their children do

**Example with Permissions:**

```
[
    'label' => 'Admin',
    'type' => 'section',
    'can' => 'access-admin',  // Hides entire section if user lacks permission
    'children' => [
        ['label' => 'Dashboard', 'route' => 'admin.dashboard', 'icon' => 'layout-dashboard'],
        ['label' => 'Users', 'route' => 'admin.users.index', 'icon' => 'users'],
        ['label' => 'Edit User', 'route' => 'admin.users.edit', 'breadcrumbOnly' => true],
        ['label' => 'Roles', 'route' => 'admin.roles.index', 'icon' => 'shield'],
    ],
],
```

**Types:**

- `'link'` - Regular navigation item (default)
- `'section'` - Container for grouping related items
- `'separator'` - Visual divider between items

**React Example:**

```
{
    navigation.map((item) => {
        if (item.type === 'section') {
            return (

                    {item.label}

            );
        }

        if (item.type === 'separator') {
            return ;
        }

        // Regular link rendering
        return {item.label};
    })
}
```

Sections and separators are automatically excluded from breadcrumbs. The output includes a `children` array for sections:

```
[
    ['id' => 'nav-main-0', 'type' => 'link', 'label' => 'Dashboard', ...],
    [
        'id' => 'nav-main-1',
        'type' => 'section',
        'label' => 'Management',
        'children' => [
            ['id' => 'nav-main-1-0', 'type' => 'link', 'label' => 'Users', ...],
            ['id' => 'nav-main-1-1', 'type' => 'link', 'label' => 'Teams', ...],
        ],
    ],
    ['id' => 'nav-main-2', 'type' => 'separator'],
    // ...
]
```

### Navigation and Breadcrumb Visibility Control

[](#navigation-and-breadcrumb-visibility-control)

Control where navigation items appear with `navOnly` and `breadcrumbOnly`:

```
'navigations' => [
    'main' => [
        [
            'label' => 'Dashboard',
            'route' => 'dashboard',
            'children' => [
                ['label' => 'Overview', 'route' => 'dashboard.overview'],

                // Hidden from main nav, only appears in breadcrumbs
                [
                    'label' => 'Edit Dashboard',
                    'route' => 'dashboard.edit',
                    'breadcrumbOnly' => true,
                ],
            ],
        ],

        // Shown in nav but excluded from breadcrumb trail
        [
            'label' => 'Admin Section',
            'route' => 'admin.index',
            'navOnly' => true,
            'children' => [
                ['label' => 'Users', 'route' => 'admin.users'],
                ['label' => 'Settings', 'route' => 'admin.settings'],
            ],
        ],
    ],
],
```

**Use Cases:**

- `breadcrumbOnly` - Perfect for edit/create pages that shouldn't clutter your main navigation
- `navOnly` - Ideal for grouping/section items that provide structure in navigation but would be redundant in breadcrumbs

**Example: Edit Pages**

```
[
    'label' => 'Users',
    'route' => 'users.index',
    'children' => [
        ['label' => 'All Users', 'route' => 'users.index'],
        ['label' => 'Edit User', 'route' => 'users.edit', 'breadcrumbOnly' => true],
        ['label' => 'Create User', 'route' => 'users.create', 'breadcrumbOnly' => true],
    ],
]
```

The navigation will show only "All Users", but breadcrumbs will display:

```
Users > Edit User

```

**Example: Navigation Sections**

```
[
    'label' => 'Administration',
    'route' => 'admin.index',
    'navOnly' => true,  // Don't include in breadcrumbs
    'children' => [
        ['label' => 'Manage Users', 'route' => 'admin.users'],
    ],
]
```

Breadcrumbs will show only "Manage Users" without the redundant "Administration" parent.

Middleware Integration
----------------------

[](#middleware-integration)

Share navigation with all Inertia requests:

```
// app/Http/Middleware/HandleInertiaRequests.php

use SysMatter\Navigation\Facades\Navigation;

public function share(Request $request): array
{
    return array_merge(parent::share($request), [
        'navigation' => [
            'main' => Navigation::get('main')->toTree(),
            'user' => Navigation::get('user_menu')->toTree(),
            'footer' => Navigation::get('footer')->toTree(),
        ],
        'breadcrumbs' => Navigation::breadcrumbs('main'),
    ]);
}
```

Testing
-------

[](#testing)

Run the test suite:

```
./vendor/bin/pest
```

With coverage:

```
./vendor/bin/pest --coverage
```

Configuration Reference
-----------------------

[](#configuration-reference)

### Navigation Item Options

[](#navigation-item-options)

OptionTypeDescription`type`stringItem type: `'link'`, `'section'`, or `'separator'``label`stringDisplay text for the item`route`stringLaravel route name (e.g., `users.index`)`url`stringExternal URL (alternative to `route`)`method`stringHTTP method for actions (`post`, `delete`, etc.)`icon`stringLucide icon name (e.g., `home`, `users`)`children`arrayNested navigation items`visible`bool|callableControls visibility (static or dynamic)`can`string|arrayGate/policy check (`'ability'` or `['ability', $model]`)`breadcrumbOnly`boolOnly show in breadcrumbs, hide from navigation`navOnly`boolOnly show in navigation, hide from breadcrumbs*custom*mixedAny custom attributes you want to include### Config Options

[](#config-options)

OptionDefaultDescription`navigations``[]`Array of named navigation structures`icons.compiled_path``storage/navigation/icons.php`Where to save compiled iconsRequirements
------------

[](#requirements)

- PHP 8.2+, 8.3+, 8.4+
- Laravel 11.0+ or 12.0+

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

Please review [our security policy](SECURITY.md) for reporting vulnerabilities.

Credits
-------

[](#credits)

- [Shavonn Brown](https://github.com/sysmatter)

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE.md) file for details.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance73

Regular maintenance activity

Popularity16

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Recently: every ~10 days

Total

17

Last Release

153d ago

Major Versions

v1.7.4 → v2.0.02025-12-16

PHP version history (2 changes)v1.0.0PHP ^8.2|^8.3|^8.4

v1.1.1PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/331bcc01f75f46dded875d74f3db055da6d74be5f8820f0a29105c6a2cd8afc8?d=identicon)[shavonn](/maintainers/shavonn)

---

Top Contributors

[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (17 commits)")[![shavonn](https://avatars.githubusercontent.com/u/3074595?v=4)](https://github.com/shavonn "shavonn (2 commits)")

---

Tags

laravelnavigationnavwayfinder

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/sysmatter-laravel-navigation/health.svg)

```
[![Health](https://phpackages.com/badges/sysmatter-laravel-navigation/health.svg)](https://phpackages.com/packages/sysmatter-laravel-navigation)
```

###  Alternatives

[nwidart/laravel-menus

Laravel Menu management

168180.3k10](/packages/nwidart-laravel-menus)[pingpong/menus

Laravel Menus

70194.4k13](/packages/pingpong-menus)[caffeinated/menus

Laravel Menus

134159.5k5](/packages/caffeinated-menus)[rinvex/laravel-menus

Rinvex Menus is a simple menu builder package for Laravel, that supports hierarchical structure, ordering, and styling with full flexibility using presenters for easy styling and custom structure of menu rendering.

294.0k20](/packages/rinvex-laravel-menus)[nedwors/navigator

A Laravel package to ease defining navigation menus

433.1k](/packages/nedwors-navigator)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
