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

Filament Menus Laravel Package

tomatophp/filament-menus

TomatoPHP Filament Menus is a flexible menu builder for Laravel and Filament apps. Create and manage menus with nested items in the admin panel, assign them to custom locations, and render dynamic navigation anywhere using a simple API.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a narrow, single-purpose Filament plugin: a CRUD resource over a menu / menu_item schema, plus two render paths — a panel navigation loader (FilamentMenuLoader) that replaces ->navigationItems() in a PanelProvider, and a Blade/Livewire component (<x-filament-menu>) for embedding outside the panel. That shape is a good architectural fit only if navigation is a domain concept you actually want in the database. If menus are owned by engineering and change per deploy, this package adds a query, a cache-invalidation surface, and an ownership liability in exchange for capability you don't need. If marketing/ops need to restructure nav without a release, or you're standing up multiple branded panels/tenant sidebars from one schema, the fit is strong and the internal equivalent is roughly 5–10 dev days.

Integration feasibility. The install path is small and well-bounded: composer require, register the plugin in the panel provider, publish config/assets, migrate, then exercise the resource. A Filament-fluent developer reaches a working menu in about half a day; add half a day if filament-shield is in play. The real feasibility question is not effort, it's the version wall.

Technical risk.

  • Version coupling is the dominant risk. v5.0.0 requires Filament v5, Laravel 12/13, PHP 8.2+. Filament 5 is a young major, so you are pairing your admin layer to first-year churn in two places at once. Mitigation is procedural, not technical: pin the package and Filament together, upgrade them as a pair, never independently.
  • Supply chain via translation. Localization resolves through lara-zeus/spatie-translatable ^2.0, a fork rather than upstream Spatie. If the app already ships spatie/laravel-translatable, expect duplicate service providers or constraint conflicts. Make that dependency call consciously at evaluation time, not during a release.
  • Maintainer concentration. 35 stars, 0 dependents, single maintainer. Adoption is effectively an ownership commitment. The v5 test suite (permission, rendering, factory, install tests) and the Laravel 12/13 × PHP 8.3/8.4 matrix materially lower the cost of forking, but they are not a support guarantee.
  • Authorization scope is narrower than it reads. "Skip items the user may not see" is documented against filament-shield. That is visibility filtering over an existing policy layer, not a per-item ACL editor. On plain spatie/permission or bespoke RBAC, verify explicitly; the failure is a silent nav leak, which is minor here and a bad assumption to carry elsewhere.
  • Two sources of truth. Leaving navigationItems() in place while enabling DB menus produces duplicated or shadowed items that are painful to diagnose. This is a process risk, and it's the most likely way a competent team ships a broken nav.

Key questions to settle before committing.

  1. Which surfaces consume menus — panel nav only, or panel plus storefront/portal headers?
  2. What is the authorization stack, and does the shield-specific filtering apply to us or do we filter in an adapter?
  3. Is translated navigation a v1 requirement or a phase-two extension? (Labels translate; there is no review queue, fallback management UI, or translator role model.)
  4. Who owns navigation content after launch — engineering, ops, or the client?
  5. Is a vendor/fork plan acceptable, and who signs off on that standing cost?

Integration Approach

Stack fit and gating. Gate on the stack first, and treat it as a hard gate. On Filament v3/v4 or Laravel ≤11 this is a non-starter unless an earlier major still receives fixes — budget a day of investigation before committing the team. On Filament v5 + Laravel 12/13 + PHP 8.2+, proceed.

Migration path. Migrate one surface at a time, and pick replace-or-augment deliberately. The recommended sequence:

  1. Wrap before you wire. Build a MenuResolver (or view composer) on day one that takes a menu key, returns a cached tree, and is the only place package classes are imported. One hour of work, one-file swap if you later fork, pin an unreleased fix, or replace the package.
  2. Replace one hardcoded panel nav. Create a menu keyed main, add a route link and an external URL, drag into order, point the panel provider at that menu. This exercises the resource, ordering, link resolution, and the panel loader in one pass. Do it as a single deliberate commit, and audit navigationItems(), navigationGroups(), and every shouldRegisterNavigation() call in the same pass — those are code-level visibility decisions now competing with DB-level ones.
  3. Prove the second render path independently. Add a footer menu and render it in a layout partial via <x-filament-menu>. Keep the component in one partial so the markup contract has a single home to re-check after upgrades.
  4. Adopt keyed menus as the addressing scheme. admin-main, client-{tenant}-sidebar, marketing-footer, resolved from panel/tenant context. Never hardcode a menu ID in a Blade file. This is where the package earns its keep across multiple shells.
  5. Centralize link resolution and validate it. Route names and model references resolve differently from external URLs. Put URL generation in the adapter and add form-level validation or an observer so stale routes and deleted-record references fail loudly in staging rather than shipping a dead nav item. If you do one integration nicety, do this one.
  6. Cache and invalidate on write. Navigation moved from compile-time to query-time, so it can now be stale and wrong after a restore. Cache the resolved tree, forget it in a model observer. Skip caching only if you measured the query, not because it looks small.

Compatibility work.

  • Pin package version and Filament version together; treat upgrades as a paired change.
  • Check for duplicate spatie/laravel-translatable providers and constraint conflicts before install, not after.
  • On any upgrade, grep for the old FilamentMenuLoader namespace — it changed in v5.0.0 and stale imports surface as a confusing class-not-found rather than an obvious menu error.
  • Re-check published views after every upgrade: overridden component copies can reintroduce the v5 fatals on items with no badge or no translation in the current locale.

Sequencing and exit criteria. Phases 1–3 are the evaluation; treat them as a go/no-go gate. If both render paths work, the package fits and you commit to the adapter pattern. If either fights you, you've learned it for under two days. Phases 4–6 are productionization and should not start until the gate passes.

Operational Impact

Maintenance. Plan to own this, modestly. Concretely: pin versions, vendor or fork rather than editing vendor files, keep package models confined to the adapter so a fork stays small, and re-verify published views and icon rendering after any theme change (the v5 icon fix is theme-coupled and a custom theme can regress it). If you add columns to the menu tables, update or wrap the shipped Menu/MenuItem factories instead of forking them in place and forgetting. Safe extension points are your resolver, published config and views, and a custom link-resolution step.

Support. There is no vendor SLA. The signals are mixed but net positive for a package this small: a real test suite, a CI matrix, and a first external contributor. None of that is a guarantee. The practical posture is: read the source before adopting (it's small — a resource plus renderers), sketch the fork plan before you need it, and keep the resolver boundary so replacing the package is a contained change.

Scaling. The schema scales fine; the operational surface is where scaling bites. Three things to decide up front:

  • Query-time navigation. Cache the resolved tree and invalidate on menu/menu-item writes. A per-request uncached tree across a multi-tenant panel estate is the predictable cost surprise.
  • Nesting depth. Drag-and-drop will happily produce deep or orphaned trees. The package is a builder, not editorial policy — agree a depth guardrail with ops.
  • Fan-out. One set of records driving a storefront header, portal sidebar, and admin nav is a genuine capability, but it also means a single bad edit changes three surfaces simultaneously. That argues for keyed menus, staged content, and the resolver-level debug command below.

Failure modes to instrument.

  • Stale nav after a restore or bad seed — the characteristic DB-driven-nav failure. Ship a small artisan command or resolver log line that dumps the resolved tree for a key; it turns a one-hour mystery into a one-minute diagnosis.
  • Duplicated or shadowed items from leaving navigationItems() alongside DB menus. Prevented by the single-commit audit, not by monitoring.
  • Dead links from deleted referenced records. Add a guard — soft deletes, morph-map discipline, or a scheduled integrity check — so you hear about it from a check, not a user.
  • Published-view regressions reintroducing v5 fatals on badge-less or untranslated items. Cover with feature tests asserting that the Blade component renders for a menu whose items have no badge and no translation in the current locale; use the shipped factories for fixtures.
  • Permission filtering assumptions carried beyond filament-shield. Verify explicitly against the real stack.

Ramp-up. Half a day for a Filament-fluent developer to a working menu; another half-day with shield; the adapter, caching, and link-validation work is where the real effort sits and should be scoped as engineering, not configuration. The onboarding artifact that matters is a one-page runbook: where menus are authored, which menu keys map to which surfaces, how to dump a resolved tree, and how to invalidate cache. Note the honest ceiling too — this is authored against Filament's rendering conventions and is not a framework-neutral menu system for a public site. The Livewire component is an embedding escape hatch, not a general-purpose renderer.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator