victoire/breadcrumb-widget
A Laravel widget for rendering configurable breadcrumb trails from your app's routes and pages. Define crumbs in PHP, output accessible markup, and drop them into Blade layouts with a simple directive.
This is not a Laravel package — it is a Symfony bundle for the Victoire CMS, a Symfony-based content management platform that ships its own "widget" system. If you are working in a Laravel codebase there is nothing to composer require here; treat this assessment as a reference for how a breadcrumb widget is meant to be wired, not as an install guide for your app.
If you actually are on a legacy Victoire/Symfony project:
composer.json and the last tag (2019-04-29). Expect symfony/* constraints in the ^2.8 || ^3.x range and PHP ^7.x. If your app is on Symfony 5/6 or PHP 8, install will fail or, worse, resolve and break at runtime.composer require victoire/breadcrumb-widget
VictoireWidget*Bundle entries:
app/AppKernel.php → new Victoire\Widget\BreadcrumbBundle\VictoireWidgetBreadcrumbBundle(),config/bundles.php if the project was migrated.bin/console cache:clear
bin/console assets:install --symlink
Where to look first in the source: Resources/views/ (the rendering template), the widget's Entity/ or Widget/ class (what fields are configurable), the Form/ type (what the editor UI exposes), and composer.json (the real compatibility story). With 2 stars and 0 dependents there is no documentation site and no community Q&A — the code is the documentation.
Rely on route/menu context rather than hand-authored trails. The durable pattern is to derive the breadcrumb from the request's route hierarchy or from the same menu tree the site navigation uses. Hardcoded item lists inside the widget drift out of sync the moment an editor renames or re-parents a page. If the bundle exposes a items collection, populate it from a resolver service, not from editor input.
Override the Twig template in your app, don't fork the bundle. Widget bundles conventionally expose templates under a VictoireWidgetBreadcrumbBundle: namespace. Copy the template into app/Resources/.../views/ (or templates/bundles/... on newer Symfony) and edit the copy. This is the one extension point that survives an abandoned dependency: template overrides are upgrade-safe, PHP class overrides are not.
Separate "structure" from "presentation" in the widget config. Editors typically want to control: whether the home crumb is shown, the separator glyph, and whether the current page is linked. Keep those as widget form fields; keep the trail itself computed. Mixing the two makes the widget unusable across more than one template.
Emit structured data at the same time as the markup. A breadcrumb whose only consumer is CSS is half-useful. Render BreadcrumbList JSON-LD from the same item array you render as <ol>/<ul> — one source of truth, two outputs:
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
{% for item in items %}
<li class="breadcrumb__item{{ loop.last ? ' is-current' }}">
{% if not loop.last and item.url %}
<a href="{{ item.url }}">{{ item.label }}</a>
{% else %}
<span aria-current="page">{{ item.label }}</span>
{% endif %}
</li>
{% endfor %}
</ol>
</nav>
Cache the computed trail, keyed on route + locale. Breadcrumb assembly is cheap per-request but easy to cache aggressively because it changes only on content edits. Key on route + params + _locale; invalidate on page save (Victoire page entities usually give you a post-persist hook).
Fallbacks belong in the resolver, not the template. If a page has no parent chain (orphaned node, 404, or a dynamically-routed detail page), return [home, current] from the resolver service. Doing it in Twig guarantees you'll forget one template.
Compose, don't duplicate. Place the breadcrumb widget in the page layout slot rather than per-page; otherwise every new page needs an editor to remember to add it, and the trail becomes inconsistent across the site.
If you're porting the idea to Laravel, the mapping is direct: a BreadcrumbService resolving from Route::current() plus a parent chain, a Blade component for the markup, Cache::remember() on the trail, and a BreadcrumbList JSON-LD partial. You will write this in an afternoon; adapting this Symfony bundle to Laravel is not a thing.
composer.json and the dependency tree before letting this into anything that faces the internet. If it already installed cleanly, pin the lockfile and treat it as frozen.repositories with a VCS entry pointing at your fork is the practical route).bundles.php, then cache:clear. Widget discovery in Victoire is cache-driven; a stale cache looks identical to a missing bundle.prod and often an assets:install if you added CSS. In dev a stale Twig cache after renaming a block is a classic 20-minute detour.aria-current="page".item values; browsers don't care about the <a href>.generateUrl) rather than concatenating path segments.victoire_widget tagged services (bin/console debug:container --tag=victoire.widget), and dump the items array before it reaches Twig. The failure is nearly always an empty item collection, not a template error.vendor/ directly — the next composer install erases it.How can I help you explore Laravel packages today?