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

Laravel Sidebar Laravel Package

maatwebsite/laravel-sidebar

A Laravel package for building configurable sidebars and navigation menus. Define items, links, icons, and active states in PHP, then render clean Blade sidebars with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require spartner/laravel-sidebar

Version 3.1.0 is the release to target: it is the first in the 3.x line with Laravel 11 support, and it is additive over 3.0.0 (no breaking changes called out in the changelog). In practice that means ^9.0|^10.0|^11.0 on the framework side and a modern PHP 8 requirement — check vendor/spartner/laravel-sidebar/composer.json before bumping if your app is still on Laravel 8.

The service provider and Blade/view namespace are registered through package auto-discovery, so there is nothing to add to config/app.php in a standard Laravel 11 skeleton. Publish the views (and any config) only when you need to change markup or defaults:

php artisan vendor:publish --provider="SpartnerNL\LaravelSidebar\LaravelSidebarServiceProvider"

Where to look first

  1. vendor/spartner/laravel-sidebar/src — the abstract Sidebar base class, plus the Menu, Group and Item objects you compose. This is the whole API surface in four files; read Item first, since almost every day-to-day change is a method call on it (url(), route(), icon(), authorize(), addItem(), prepend()/append()).
  2. The package's default Blade views — the reference markup to copy into your own layout or override.
  3. README.md in the package root — the canonical rendering snippet (@sidebar(...) directive / $sidebar->render() depending on version) and the exact namespaces used by the 3.x fork.

First use case — one sidebar, one group, a handful of items

Create app/Sidebars/MainSidebar.php, extend the package's Sidebar, and build the menu. The fork renamed namespaces away from the abandoned Maatwebsite\Sidebar package, so copy the use statements from the installed source rather than from old blog posts:

namespace App\Sidebars;

use SpartnerNL\LaravelSidebar\Library\Core\Group;
use SpartnerNL\LaravelSidebar\Library\Core\Item;
use SpartnerNL\LaravelSidebar\Library\Core\Sidebar;

class MainSidebar extends Sidebar
{
    public function getMenu()
    {
        $this->menu->group('main', function (Group $group) {
            $group->item(__('Dashboard'), function (Item $item) {
                $item->route('dashboard');
                $item->icon('fas fa-home');
            });

            $group->item(__('Customers'), function (Item $item) {
                $item->route('customers.index');
                $item->icon('fas fa-users');
                $item->authorize(auth()->user()->can('viewAny', Customer::class));
            });
        });

        return $this->menu;
    }
}

Then render it once in your authenticated layout so every page inherits the menu. That single class is the 20% of the package you will use 80% of the time; everything else (groups, sub-items, badges, custom views) hangs off it.

Implementation Patterns

Let each module own its slice of the menu. Rather than one 400-line MainSidebar, register groups/items from the service provider of the feature they belong to, so removing a package removes its navigation. The sidebar is resolved from the container, so a provider can grab it and prepend()/append() to an existing group. This is the single most valuable pattern for keeping a growing admin menu maintainable.

Prefer route names over URLs. Use $item->route('customers.show', $customer) instead of $item->url('/customers/'.$id). Route-name items get active-state detection and URL generation for free, survive route prefix/domain changes, and don't break when you rename a URI. Reserve $item->url() for genuinely external links (docs, status page, marketing site).

Authorize in the menu definition, not the view. authorize() with a gate/policy result removes the item entirely for users who can't use it. Keeping the checks next to the item means a new permission is a one-line diff, and you never render a link that 403s. Use Gate::allows(...)/$user->can(...) consistently — mixing authorize() in some places and @can in the Blade view produces menus whose shape is impossible to reason about.

Model the hierarchy deliberately. Groups are section headers (and render as separate blocks); sub-items are the expandable second level. Anything deeper than two levels is almost always a UX problem, not a sidebar API problem — flatten it.

Translate at build time. __('Customers') inside the item callback keeps the sidebar locale-aware without touching the views, and the same strings feed your breadcrumbs.

Cache the structure, not the result. Building the menu on every request is cheap at 20 items and not cheap at 200 with per-item queries. If you cache, cache the unfiltered structure and apply authorization after retrieval — caching a menu that has already been filtered per user is a reliable way to show an admin's navigation to a regular user after a role change.

Test the sidebar class, not the HTML. Assert route names, active flags and visibility per user role by instantiating MainSidebar and walking getMenu(). One or two rendered-HTML snapshot tests catch markup regressions; asserting on <li> classes for every item does not.

Keep your own layout/CSS ownership. Publish the views and treat them as yours. The default markup is generic; almost every project restyles it, and once published you are in control of upgrades to that file.

Gotchas and Tips

  • 3.1.0 is a compatibility release, not a feature release. The only change is Laravel 11 support. Upgrading from 3.0.0 carries no code changes on your side; upgrading from 2.x/1.x is a major-version jump (namespace rename away from Maatwebsite\Sidebar, plus signature changes) — budget a real migration for the use statements and method signatures across every sidebar class.
  • Composer will silently keep you on 3.0.0 if your framework constraint or PHP version doesn't resolve. Run composer why-not spartner/laravel-sidebar 3.1.0 after composer update rather than assuming Laravel 11 support landed.
  • Auto-discovery can be off. If bootstrap/cache/packages.php has no entry for the package, someone has dont-discover configured or a stale cache. php artisan package:discover then php artisan config:clear is the fix; the symptom is a "target class [sidebar] does not exist"-style binding error.
  • The sidebar builds on every layout render. A Customer::count() inside an item callback becomes a query on every page in the app. Move counts to a view composer or a cached service, and remember to invalidate on deploy.
  • "Item is missing" is nearly always authorization or a route-name typo. authorize(false), a policy that doesn't exist, or route('customers.index') when the route is admin.customers.index will hide or throw silently depending on context. Temporarily dump() inside the closure, or run php artisan route:list | grep customers, before touching the sidebar code.
  • Active-state bugs come from mixing URL and route items and from trailing slashes / query strings. Pick route names and stay there.
  • Ordering is request-scoped. Items built in a provider run before render; append()ing from a controller after the layout has started rendering won't show up. If ordering matters, control it in the sidebar class or via explicit prepend() in the relevant provider.
  • Published views stop receiving fixes. Once you vendor:publish, minor-version markup tweaks won't reach you — diff the package view against yours when you upgrade.
  • Laravel 11 has no config/ directory by default. If the package ships a config file you intend to tune, publish it explicitly; editing a file that doesn't exist after the upgrade is a common dead end.
  • Watch the 3.x line for Laravel 12 support — the changelog here is a single-contributor compatibility PR, so the maintenance cadence is worth checking before you build deeply on top of it; keep your sidebar definitions in app/Sidebars (application code) rather than subclassing package internals so a future fork/swap stays cheap.
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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
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