tobiasnagel / flux-breadcrumbs
Route-driven breadcrumbs for Laravel applications rendered with Flux UI.
Requires
- php: ^8.4
- illuminate/contracts: ^13.0
- illuminate/routing: ^13.0
- illuminate/support: ^13.0
- illuminate/view: ^13.0
Requires (Dev)
- orchestra/testbench: ^11.0
- phpunit/phpunit: ^12.0
Suggests
- livewire/flux: Required to render the bundled breadcrumbs view (^2.0).
Provides
None
Conflicts
None
Replaces
None
README
Route-driven breadcrumbs for Laravel applications rendered with Flux UI.
Declare a label, an optional parent and an optional icon directly on your routes. The package walks the parent chain of the current route and renders it with Flux's <flux:breadcrumbs> component. No breadcrumb files, no manual trail building.
Requirements
- PHP 8.4+
- Laravel 13
- Flux UI 2.x (
livewire/flux), installed separately. It is only suggested by this package but is required to render the bundled view.
Installation
composer require tobiasnagel/flux-breadcrumbs
The service provider is registered automatically via package discovery.
Optionally publish the config file:
php artisan vendor:publish --tag=flux-breadcrumbs-config
Usage
Defining breadcrumbs
The package registers a breadcrumb() macro on routes:
Route::breadcrumb(string $label, ?string $parent = null, ?string $icon = null)
$parent is the full name of another route that also has a breadcrumb. Chain routes together to build the trail:
use Illuminate\Support\Facades\Route; Route::get('/dashboard', DashboardController::class) ->name('dashboard') ->breadcrumb('Dashboard', icon: 'home'); Route::get('/users', [UserController::class, 'index']) ->name('users.index') ->breadcrumb('Users', parent: 'dashboard'); Route::get('/users/{user}', [UserController::class, 'show']) ->name('users.show') ->breadcrumb('{user.name}', parent: 'users.index');
Visiting /users/42 renders:
🏠 › Users › Jane Doe
Only scalar values are stored on the route action, so breadcrumbs work with php artisan route:cache.
Rendering
Include the bundled view in your page layout or a regular Blade view:
@include('flux-breadcrumbs::breadcrumbs')
The view resolves the trail from the current request's route, so nothing needs to be passed in. Routes without a breadcrumb definition render nothing.
When using Livewire, place the include in the page layout, outside the component's re-rendered view. During component updates, the current request belongs to Livewire's update endpoint rather than the original page route. That endpoint normally has no breadcrumb definition, so breadcrumbs included inside the component disappear after an update. The package does not preserve the original page-route context.
Dynamic labels
Labels may contain placeholders in curly braces. They are resolved against the bound parameters of the current route using dot notation, so you can reach into route-model-bound instances:
->breadcrumb('{user.name}', parent: 'users.index') ->breadcrumb('{project.team.name} / {project.title}', parent: 'projects.index')
Placeholders that cannot be resolved are replaced with an empty string.
Relationships that are not loaded yet are eager-loaded explicitly when the label is resolved. This works with Model::preventLazyLoading() enabled, but costs one query per unloaded relationship, so eager-load relationships you use in labels where that matters.
Scalar and stringable values are converted to strings. Backed enums resolve to their backing value, while unit enums resolve to their case name. Other values are replaced with an empty string. Enum handling applies to both implicitly bound route enums and enum-valued model attributes:
->breadcrumb('{status}') ->breadcrumb('{post.status}')
You can also explicitly select .value for a backed enum's value or .name for any enum's case name, for example {status.value} or {post.status.name}.
Parent route parameters
Parent URLs are generated with route() using only current-route parameters whose names match parameters declared by the parent route. Nested resource routes work when the required parent parameters are available under the same names, or supplied by Laravel URL defaults.
The package does not infer missing parameters from model relationships or support parameter mappings. For example, a shallow child route /tasks/{task} cannot link to a breadcrumb parent /projects/{project}/tasks unless project is otherwise supplied, even if the bound task has a project relationship. A missing required parameter causes an Illuminate\Routing\Exceptions\UrlGenerationException during rendering.
Use a nested child route such as /projects/{project}/tasks/{task}, choose a parent whose parameters are available, or configure the required Laravel URL defaults.
Icons
Pass an icon name (any Heroicon supported by Flux) as the third argument. The label is still passed to the item and is also used as its title and aria-label, keeping the item accessible:
->breadcrumb('Dashboard', icon: 'home')
The icon variant is controlled by the icon_variant config option.
Configuration
config/flux-breadcrumbs.php:
| Key | Default | Description |
|---|---|---|
wire_navigate |
true |
Render links with wire:navigate for SPA-style navigation. Set to false for full page loads. |
separator |
null |
Separator between items. null uses the Flux default chevron. Use slash or any Heroicon name. |
icon_variant |
mini |
Flux icon variant for items with an icon: outline, solid, mini or micro. |
min_items |
1 |
Only render the trail when it contains at least this many items. Set to 2 to hide it on root pages. |
Customising the view
Publish the Blade view to resources/views/vendor/flux-breadcrumbs and edit it freely:
php artisan vendor:publish --tag=flux-breadcrumbs-views
If you prefer to build your own markup, inject TobiasNagel\FluxBreadcrumbs\BreadcrumbResolver and call resolve($route). It returns an array of BreadcrumbItem objects with public label, url and icon properties. The current page has a null URL.
Behaviour
- The current page is rendered as plain text, not as a link.
- A
LogicExceptionis thrown when:- a
parentreferences a route name that does not exist, - a route in the parent chain has no breadcrumb definition,
- the parent chain contains a cycle.
- a
AI agent support (Laravel Boost)
The package ships a Laravel Boost skill (flux-breadcrumbs-development) and a short guideline under resources/boost/. When this package is a direct dependency of your application and you run php artisan boost:install or php artisan boost:update, Boost installs the skill for your coding agent (for example into .claude/skills/) and includes the guideline in the generated agent instructions. No configuration is required.
Testing
composer test
composer test-coverage
The coverage script needs Xdebug (or PCOV) to be loaded. With Laravel Herd, Xdebug is not enabled by default; pass it explicitly:
XDEBUG_MODE=coverage php -d zend_extension=/Applications/Herd.app/Contents/Resources/xdebug/xdebug-84-arm64.so vendor/bin/phpunit --coverage-text
License
MIT