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 Pinnable Navigation Laravel Package

devletes/filament-pinnable-navigation

Filament plugin that lets users pin sidebar navigation items into a dedicated Pinned group, with localStorage or database persistence, configurable icons, group title, accordion mode, and a page-header pin toggle for resources.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and register the plugin — that's genuinely the entire minimum:

composer require devletes/filament-pinnable-navigation
use Devletes\FilamentPinnableNavigation\PinnableNavigationPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(PinnableNavigationPlugin::make());
}

That's it. The default mode is database_enabled = false, which uses browser localStorage keyed by panel ID and authenticated user — no migrations, no config publishing, no extra setup required for the first use case.

Where to look first: the README covers install, plugin registration, config options, and persistence modes. That's essentially the whole public API surface — there is no deep customization API beyond config and DB persistence.

First use case: log in, hover a grouped sidebar item, click the star icon. It moves into a synthetic "Pinned" group at the top of the sidebar. From the same account in another browser, verify the pin persists (localStorage per user). Then toggle show_in_resource on to get the page-header pin button on resource index pages.

Verify your panel uses Filament's default grouped navigation before installing — this package manipulates those groups; heavily customized navigation may not play nicely.

Implementation Patterns

Panel-scoped registration. Register per-panel, not globally, so multi-panel apps can offer pinning selectively:

$panel->plugin(PinnableNavigationPlugin::make());

Pins are already scoped per panel and per user — a pin in admin won't show up in staff.

Start with localStorage, graduate to DB later. The default is zero-friction. Publish config only when you need persistence across devices/browsers or want to reason about pin data server-side:

php artisan vendor:publish --tag="pinnable-navigation-config"

Flip database_enabled to true, publish migrations, run them:

php artisan vendor:publish --tag="pinnable-navigation-migrations"
php artisan migrate

Config-as-feature-toggles. The config array is the real control surface. Useful patterns:

  • group_title / group_icon — rebrand "Pinned" to your domain language (e.g., "Favorites" with heroicon-o-bookmark).
  • pin_icon / unpin_icon — pair these as outline/filled variants so the toggle reads as a state change visually.
  • accordion_mode — set false if your users are already used to Filament's default multi-open grouped nav and the accordion behavior feels restrictive.
  • show_in_resource — leave true if power users live inside resource index pages; disable if it crowds the header on pages where you've added your own actions.

Persistence pattern decisions. localStorage is the right pick for single-device admin panels where UX polish matters. DB-backed is the right pick when:

  • Users switch between laptop/desktop/mobile.
  • You want to expose "most pinned items" analytics later via a query on pinned_navigation_items.
  • Multi-tenant deployments where you want to keep pin state in your own data store for backup/portability.

Deployment pattern. Because pins are UI state, treat rollout as a soft feature: no feature flag is provided, but registration per-panel means you can enable it for one panel first as an implicit staged rollout.

Gotchas and Tips

Filament 5 and PHP 8.2 are hard requirements. Filament 4 or PHP 8.1 projects cannot use this. Check composer.json before assuming.

database_enabled defaults to false. Enabling it without running migrations produces silent pin failures — the toggle appears to work but nothing persists. Always publish migrations and run them together with the config flip.

Publishing config doesn't publish migrations. They are two separate tags:

php artisan vendor:publish --tag="pinnable-navigation-config"
php artisan vendor:publish --tag="pinnable-navigation-migrations"

Easy to miss.

localStorage is per panel and per user. Two users on one browser won't see each other's pins (good), but two panels for the same user won't share pins either. If you want pins to feel "global" across panels, you'll need DB mode plus your own cross-panel sync — not provided.

Clustered items have been a known bug source. Release 1.0.2 fixed clustered Filament items leaking into the main sidebar. If you're on an older version and see duplicate entries in the sidebar, upgrade.

Collapsed sidebar behavior arrived in 1.0.4. Pinned items show in a dropdown when the sidebar is collapsed. Pre-1.0.4, pins may appear to "disappear" in minimized mode — that's the version, not a bug.

Accordion mode changes the feel globally. Setting accordion_mode = true (the default) affects all managed navigation groups' open/close behavior, not just the pinned group. Users who expect multi-open grouped nav will notice. This is the most likely "why does the sidebar behave differently?" support ticket — document it in your changelog.

No hooks, events, or extension points. There's no NavigationItemPinned event, no way to intercept the toggle, no permission check built-in. If you need role-restricted pinning, per-tenant limits, or analytics on pin actions, you'll be writing that outside the package (a wrapper service or a small fork).

No native multi-tenancy. In DB mode with tenancy, the pinned_navigation_items table isn't tenant-scoped out of the box. Add a tenant_id column via a follow-up migration and filter reads accordingly, or accept that pins are global per user across tenants.

Debugging persistence: check DevTools → Application → Local Storage for a per-panel/per-user key before assuming the DB is broken. In DB mode, SELECT * FROM pinned_navigation_items tells you immediately whether the write path works.

Asset registration is automatic (CSS/JS via Filament's asset manager), but if pins render unstyled after an upgrade, clear Filament's asset cache — the package ships prebuilt minified dist assets (since 1.0.3).

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.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk