Menus
The filament-menus plugin is a small menu builder for the public site: it owns the data and a Filament resource, plus a cached render API. It is a first-party Qcentic package (Plugins) and one of the navigation pieces a clone enables per Build a product.
What the plugin owns
- Table — a single
menu_itemstable. There is no separatemenustable; a menu is the value of thelocationcolumn. The migration ships with the package.
| Column | Type | Notes |
|---|---|---|
id |
bigint | Primary key |
location |
string | header or footer — the menu name |
label |
string | Link text |
url |
string(2048) | Absolute URL or app-relative path (/about) |
icon |
string, nullable | Blade icon name (e.g. lucide-github); resolved by the app |
target |
string | _self (default) or _blank |
position |
unsigned int | Order within a location; default 0 |
created_at / updated_at |
timestamp | — |
Index on (location, position) drives the ordered reads.
- Model —
MenuItem(Mamenein\FilamentMenus\Models\MenuItem). Fillablelocation,label,url,icon,target,position. ConstantsLOCATION_HEADER/LOCATION_FOOTERandTARGET_SELF/TARGET_BLANK. Oncreating,positionauto-increments tomax(position) + 1for that location; onsaved/deleted, the location cache is busted (and the previous location's cache when an item is moved). - Resource —
MenuItemResourcein the panel, navigation groupSite, labelMenus, iconHeroicon::OutlinedBars3, sort10. Form: location select, label, url, icon, target. Table: label (searchable), location badge, url (truncated), icon (toggleable), target badge, position (sortable, drag-to-reorder); a location filter; reordering busts all caches. - Plugin object —
FilamentMenusPlugin(getId()returnsmenus), registered with$panel->plugin(FilamentMenusPlugin::make()).
Render API
MenuItems::for('header') returns an ordered, cached Collection<int, MenuItem> for one location. Results are cached per location under filament-menus.{location} for one day, stored as plain attribute arrays (binary-safe for libSQL cache stores). MenuItems::forget($location) and MenuItems::forgetAll() bust manually. Uncached access (tooling, seeds): MenuItem::forLocation('header').
What the plugin does NOT ship
Public Blade. The package stops at the data and the render API; the clone iterates the collection in its own layout and decides the markup, classes, and icon set. The plugin is look-neutral by design (Build a product).
Authorization
MenuItemResource::canAccess() gates the resource to users with the super_admin role — Spatie permission, surfaced in the panel by Filament Shield. The same super-admin gate is used across the first-party plugins.
Status
v1 ships flat items only (no nesting) and the two fixed locations, header and footer. Deeper topic pages — custom locations, nesting, Shield permission matrix per role — will be added as the plugin's scope is locked.
flowchart LR
A["MenuItemResource (panel)"] --> B["menu_items table"]
B --> C["MenuItems::for(location)"]
C --> D["clone layout render"]
B -.saved/deleted.-> E["forget(location) cache"]
E --> C