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 Nova Sidebar Links Laravel Package

gabrieliuga/laravel-nova-sidebar-links

Add custom links to your Laravel Nova sidebar with minimal setup. Configure internal routes, external URLs, and custom menu entries from a simple config file, keeping your Nova navigation organized and tailored to your workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. This is a Nova-only package. If the project isn't already running Laravel Nova with a valid license and NovaServiceProvider in config/app.php (Laravel 7+) or bootstrap/providers.php (Laravel 11+), there is nothing here for you. Check the package composer.json for the exact Nova and Laravel constraints — the package is on a 1.x line last tagged in April 2020, so on Nova 4/5 you should expect to either pin an older Nova or patch a constraint.

Install

composer require gabrieliuga/laravel-nova-sidebar-links

Then check whether the service provider is auto-discovered (extra.laravel.providers in the package's composer.json). If not, register it manually, and publish the config if one ships:

php artisan vendor:publish --provider="Gabrieliuga\LaravelNovaSidebarLinks\SidebarLinksServiceProvider"

Where to look first, in order

  1. README.md — the config example is the entire API surface. There is no fluent builder to learn; you're editing an array.
  2. config/nova-sidebar-links.php (or whatever the published name is) — this is where links, labels, URLs, icons, and canSee-style closures live.
  3. The service provider in src/ — this tells you how it renders (a custom Nova:: menu macro, a NovaServiceProvider::boot() hook, a Blade view override). Knowing the mechanism is what lets you debug a link that doesn't appear.
  4. PR #3, which is the entire content of v1.0.5. The release notes are a thank-you note; the diff is the changelog.

First use case. Add exactly one link — an external "Status Page" or "Runbook" — with a label, a URL, and a target="_blank" if the package supports it. Load /nova, confirm it renders in the sidebar with the right icon weight, then stop and decide whether the remaining links are worth the dependency versus a 15-line Nova:: snippet in NovaServiceProvider::boot().

Implementation Patterns

Treat the config file as the source of truth. The whole value proposition is "links defined in one place, rendered by Nova." Resist the urge to also register links imperatively elsewhere — the moment half your links live in config and half in a provider, ordering becomes guesswork and nobody knows where to add the next one. If the config file grows past ~10 entries, that's a signal you want a Nova tool, not a bigger array.

Environment-driven URLs. Hardcoding https://status.example.com in a link is fine; hardcoding an internal-only host is not. Read from config('services.status_page.url') or an env var so staging doesn't link to production and local doesn't link to a host that only resolves inside the VPC. The same applies to presence: a "Feature Flags" link should not render on a machine where the flag service isn't configured.

Authorisation belongs in the closure, and also in the route. If the package supports a visibility callback, use Gates/Policies rather than role strings:

'canSee' => fn ($request) => $request->user()->can('viewAny', Invoice::class),

This keeps sidebar visibility consistent with the rest of your authorization model and survives a role refactor. But understand the contract: hiding a link is not access control. The destination route must enforce its own policy. A link that disappears from the sidebar is a UX affordance, not a security boundary — anyone who knows the URL still gets there. This is the most common mistake with link packages and it's the thing to say out loud in code review.

Explicit ordering, always. Do not rely on registration order or array order if the package offers an order/sort key — use it. The moment another Nova package (or a future you) inserts a menu item, implicit ordering produces output that looks nondeterministic and gets blamed on the wrong package. If the package supports grouping or a section/"menu section" target, attach to an existing section rather than creating a new one; Nova sidebars get noisy fast and section collisions between packages are a recurring annoyance.

Icons from Nova's own set. Mixing icon libraries (Heroicons v1, Font Awesome, whatever the package defaults to) produces visible weight and alignment mismatches against the resource icons. Pick from the icon set Nova itself uses for the target Nova version and stop there.

Localise the labels. __('nav.status_page') costs nothing now and saves a sweep later. External link labels are user-facing strings just like any other.

Test it as behaviour, not as configuration. Two feature tests cover 90% of regressions across a Nova or package upgrade:

public function test_sidebar_shows_status_link_for_permitted_user() { /* GET /nova, assertSee */ }
public function test_sidebar_hides_billing_link_for_unauthorised_user() { /* assertDontSee */ }

Nova renders the sidebar server-side for the initial paint, so assertSee on /nova works. These tests are what turn "the sidebar broke after the Nova upgrade" from a Friday-afternoon incident into a red CI run.

When you outgrow it, leave. The instant a requirement needs a badge count, a dropdown, a divider with behaviour, or a link that changes per-record, stop extending this package. Write a proper Nova tool: a small Vue component registered in NovaServiceProvider::tools(). Fighting a links-only package into being a menu system costs more than the custom tool would have.

Gotchas and Tips

Compatibility is the entire risk profile of this package. One maintainer, a 1.x version, last release April 2020, and it hooks into Nova's menu internals — which Nova has changed across majors. Read the composer.json constraint, not the README badge. Pin the package version and the Nova version, and upgrade them together with a green sidebar test.

v1.0.5 is a community patch with no written changelog. The release notes are literally a thank-you to a contributor (PR #3). Read the diff before upgrading. It may be a one-line compatibility fix or a behaviour change; "no notes" does not mean "no change," but it also doesn't warrant a full regression pass. Upgrade promptly, verify with your existing sidebar test, move on.

Config caching will bite you. In production with php artisan config:cache, a newly added link in the config file will not appear until you rebuild the cache. Deploy scripts that run config:cache before the new code is in place, or that skip it, are the usual culprits. If a link works locally and not on staging, check this first.

Debugging a missing link — work outward, not inward. In order:

  1. Is the service provider registered and is the config published/merged? (php artisan about or config('nova-sidebar-links') via tinker.)
  2. Is the call site actually reached? Drop a dd() in the provider's boot or the registrar.
  3. Is the visibility closure returning false? This is the answer nine times out of ten — dd($request->user()->can(...)).
  4. Is the link rendering but off-screen or ungrouped? Inspect the assembled menu/section collection Nova builds, or just view-source the /nova response.

Reach for "package bug" last. On a package this small, the fault is almost always your config, your closure, or your cache.

Ordering collisions between packages. Two packages inserting into the same section with default ordering produce output that looks random and shifts between deploys. Set explicit order values so the result is stable regardless of what else is installed, and so you can point at the value in a bug report.

Don't let the config file become a permission matrix. If visibility logic per link grows into multi-line closures with three && conditions, it belongs in a Policy method ($user->can('seeBillingLink')) that the config merely references. Config files are for declarative data; business rules hidden in them are unreviewable and untestable.

Treat it as a convenience, not infrastructure. There's no SLA, no security response commitment, and no second maintainer. That's acceptable for a static set of sidebar links; it is not acceptable for anything an auditor will ask about. If the maintainer goes quiet for a release cycle, the migration path is trivial — inline the equivalent Nova:: snippet in NovaServiceProvider::boot() — and you should know that path before you need it, not after.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console