Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Breadcrumbs Bundle Laravel Package

lafourchette/breadcrumbs-bundle

A Symfony bundle for building and rendering breadcrumb trails. Define breadcrumbs through service configuration or annotations, then display them in Twig templates with minimal setup for consistent navigation across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check: lafourchette/breadcrumbs-bundle is a Symfony bundle, not a Laravel package. There is no Illuminate\Support\ServiceProvider, no facade, no config/breadcrumbs.php, and no package auto-discovery. composer require lafourchette/breadcrumbs-bundle inside a Laravel app will install files that Laravel never boots. So "getting started" branches immediately:

  • If you (or the team) actually maintain a Symfony app, register LaFourchette\BreadcrumbsBundle\LaFourchetteBreadcrumbsBundle in config/bundles.php, then read DependencyInjection/Configuration.php and Resources/config/services.xml before the README. Those two files tell you the real service IDs, options, and defaults — the README is the most likely thing to be stale.
  • If you are in Laravel (the stated premise), treat this repo as a reference implementation, not a dependency. Its whole surface area is small: build a trail, expose it to the template layer, render it in the layout. Port that shape into a Breadcrumbs singleton bound in a service provider plus a Blade component.

Where to look first, either way:

  1. The bundle's service definition — this is the actual API. Anything not wired there does not exist.
  2. Its Twig extension (the render entry point). This is the only thing your templates will touch.
  3. The item/collection class — this is what you'd subclass if you need extra attributes.

First use case: a three-level trail — Home > Section > Current page — rendered from the layout so it appears on every page. Start with a hard-coded trail in one controller action to prove wiring end to end, then move definitions into whatever mechanism the bundle supports once rendering works. Do not start by making it dynamic across the whole site.

Signal to weigh: 0 dependents and no star count listed. That is an unmaintained-package profile. Budget for reading the source and possibly forking, not for composer update just working.

Implementation Patterns

Build the trail in the controller or a dedicated builder — never in the template. Templates should receive a finished collection and do nothing but loop. The moment you start conditionally pushing items inside Twig/Blade you lose the ability to reuse the trail for JSON-LD, sitemaps, or tests.

Per-section builders for repeated trails. If /admin/users/* always sits under Admin > Users, define that once (a builder class, or a route-name → trail map in config) instead of repeating three addItem calls in fifteen actions. This is the single highest-leverage pattern and it is what makes breadcrumbs stop rotting as the app grows.

Render from the layout, override per page. Put the render call in the base layout so nothing is silently missing, and let individual actions replace the trail wholesale rather than appending to whatever the layout seeded.

Last item has no URL. The current page should render as plain text with aria-current="page", not a link to itself. Make the renderer treat null/empty URL as "current" so you cannot accidentally emit a self-link.

Translate at render time, not build time. Store labels as translation keys and resolve them in the template. If you resolve when pushing, a locale change mid-request (or a cached trail shared across locales) bakes in the wrong language.

Emit structured data from the same array. Loop the identical collection twice: once for HTML, once for a BreadcrumbList JSON-LD block. Markup and schema then cannot drift, which is the usual failure mode when SEO breadcrumbs are maintained by hand.

Laravel port shape:

// AppServiceProvider::register()
$this->app->scoped(Breadcrumbs::class, fn () => new Breadcrumbs());

// in a controller
breadcrumbs()->push(__('nav.home'), route('home'))
             ->push(__('nav.users'), route('users.index'))
             ->push($user->name);          // current page: no URL

// resources/views/layouts/app.blade.php
<x-breadcrumbs :items="breadcrumbs()->all()" />

Use scoped (not singleton) — see the Octane gotcha below.

Gotchas and Tips

  • Symfony-only means Symfony-only. No auto-discovery, no vendor:publish, no Blade directive, no config/ merge. Installing it in Laravel is dead weight unless you are explicitly porting it. Say this out loud in the PR description so the next developer does not spend an afternoon wondering why nothing renders.
  • Stateful trail + long-running workers. If the breadcrumb service is a shared singleton, it accumulates items across requests under Symfony RoadRunner/Swoole or Laravel Octane. You will see "Home > Users > Home > Orders". Bind per-request (scoped in Laravel) or reset the trail at the start of each request.
  • Port the renderer, not just the data structure. The <a>-vs-<span> decision, separator handling, and escaping logic is where the bugs actually live. Copying only the item class gets you a data structure and a broken template.
  • Escaping. Labels frequently contain user data (page titles, entity names). Ensure the renderer escapes by default and that any raw output is a deliberate, reviewed decision — this is a stored-XSS vector if labels come from the database.
  • Debugging "the breadcrumb is missing." Dump the collection immediately before render. Nine times out of ten it is one of: trail built in a listener that runs before the controller populated the entity, child template not extending the layout, or the layout rendering before the builder runs.
  • Don't derive breadcrumbs from the URL path when you have route parameters and named routes. Route-name-driven trails survive slug changes and are translatable; explode('/', $path) trails are neither.
  • Extension points are thin. The item class and renderer are the only sensible hooks for icons or schema.org attributes. Subclass rather than patch vendor/; but given the maintenance profile, an outright fork with your changes on main is the more honest move.
  • Pin the version and read the source. With no dependents and no star signal, assume the README examples may target an older Symfony. The bundle is small enough to audit in under an hour — do that instead of trusting the docs.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource