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

Nova Resource Group Menu Laravel Package

saintsystems/nova-resource-group-menu

Organizes Laravel Nova resources into collapsible sidebar groups, making large admin panels easier to navigate. Adds grouped menu sections, configurable labels, and icons so related resources stay tidy without custom tooling.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a presentation-layer package, not a platform component. It does not own data, expose APIs, or introduce new domain concepts — it reads the static $group property that Nova already renders on each Resource and converts the resulting flat headings into labelled, collapsible sub-menus. From a TPM's chair that is the important framing: the blast radius is confined to the admin sidebar's information architecture, and the underlying resource registry, routing, authorization, and policies are untouched. That makes it cheap to trial and cheap to abandon. It also means the capability is not differentiated — Nova 4+ ships Nova::mainMenu() with MenuGroup / MenuSection and collapsible groups natively, which turns this package into a reference implementation rather than a strategic dependency.

Integration feasibility. Feasible but entirely version-gated. The last release is 0.1.0 (2020-05-12), placing it in the Nova 2.x/3.x era. On Nova 4/5 the Vue 3 / Inertia rewrite almost certainly breaks the asset layer, so the gate is a one-line check of laravel/nova in composer.lock before any engineering time is committed. On Nova 2/3 the integration is a composer require, an optional vendor:publish, a nova:publish for assets, and assigning $group constants across Resource classes. The README is effectively empty, so the source is the documentation — budget an hour to read it and confirm whether it hooks a public Nova API or reaches into internals, since that determines how brittle the integration is against patch-level Nova bumps.

Technical risk. The risk profile is asymmetric and dominated by ownership, not licensing. MIT means "buy" is free, so the real decision is build vs. borrow. With 27 stars, zero dependents, and no release in roughly five years, we are the QA function — nobody else has incidentally compatibility-tested this against our Nova/PHP/Laravel triple. The dangerous failure is silent rather than loud: a boot-time exception takes the panel down and is obvious, but a Nova minor upgrade that leaves the menu rendering while groups flatten or resources drop out surfaces as an operator filing "the sidebar looks wrong" six weeks later. Secondary risks are routine for a 2020 codebase on PHP 8.1+ — dynamic-property and implicit-nullable deprecations that escalate to hard failures on a PHP minor bump — and conflicts with any existing custom menu, theme, or sidebar tool, which are painful to bisect because two packages mutating the same menu look like either one misbehaving.

Key questions.

  1. Which Nova major are we on, and is staying there deliberate or drift? The 2020 release date forces that platform decision explicitly.
  2. Is sidebar density a validated operator pain point with named evidence, or a hunch from a design review?
  3. Who is the named owner — a PHP/Laravel engineer willing to vendor or fork the source, with a recurring allowance against Nova upgrades?
  4. Have we confirmed the capability gap cannot be closed in ~100 lines in NovaServiceProvider, a file we already own?
  5. Does our dependency-approval process apply? Low stars, zero dependents, and stale releases fail most audit gates, and fighting that costs more than the build.
  6. Is the real problem resource count or permission sprawl rather than menu nesting? Trimming what's exposed usually beats nesting what isn't.

Integration Approach

Stack fit. Correct fit only for Nova 2/3 shops with an established Laravel codebase and an existing PHP owner. It composes cleanly with Nova's authorization model — groups are navigation chrome, while Authorizable and policies still decide what renders — so there is no second permission layer to design or defend. The recommended pattern treats $group as the single source of truth and centralizes labels as constants in one class (app/Nova/Groups.php) so group names are greppable and renameable in one place; a typo in $group silently creates a new group rather than erroring, which is exactly the kind of defect that reaches production unnoticed.

Migration path. Two distinct paths, and the TPM should pick one deliberately rather than defaulting.

  • Borrow (Nova 2/3, prototype intent): install on a throwaway branch, read the source, publish and commit the config, then run a smoke test. Use as an IA prototype to generate evidence, with the explicit expectation that it is not defended in a review six months from now.
  • Build (recommended endpoint): reimplement natively in NovaServiceProvider::boot() via Nova::mainMenu() returning MenuSection::make(...) collections — roughly a hundred lines, a file we already own, with our name on the git blame. On Nova 4/5 this is not a migration, it is simply the only supported path, and the package becomes a tutorial we read once in under an hour to learn where the sidebar hooks live in our version.

Compatibility. Pin exactly ("saintsystems/nova-resource-group-menu": "0.1.0"), never with a caret. Run any spike with APP_DEBUG=true and the error log open to catch deprecation noise before it becomes a failure. Asset publishing is the usual cause of "it installed but does nothing": if config loads and $group values are correct but headings stay flat — or you see a heading nested inside a heading from Nova's own <h3> — check public/vendor/nova and re-run php artisan nova:publish, clearing Nova's aggressively cached compiled assets between attempts. If resources vanish entirely rather than flattening, that is a genuine incompatibility; roll back.

Sequencing.

  1. Version gate: read composer.lock for laravel/nova. Nova 4/5 stops here — use the native API.
  2. Spike on a throwaway branch; read src/ and resources/ before trusting anything.
  3. If the team already runs a custom menu, theme, or another sidebar tool, install this last and test with the others disabled first.
  4. Define Groups constants and group by operator domain (Billing, Catalog, Support, Users & Access) — not by model or database schema. A group with one resource in it probably shouldn't be a group.
  5. Publish and commit config with an explicit, complete ordering array; an unlisted group's position is undefined behaviour you discover in production.
  6. Ship a render smoke test in CI before the first deploy (below).
  7. Record the ownership decision alongside the version pin — vendor with a named owner, or reimplement. A floating Composer dependency with no owner is the one outcome with no good ending.

Instrumentation to build alongside it. If the goal is evidence rather than aesthetics, pair the prototype with something measurable: task time to locate a resource, support tickets phrased "where is X," and an operator survey score. That converts a vague complaint into an artifact suitable for prioritization, and it is the deliverable that outlives the package regardless of which path you take.

Operational Impact

Maintenance. This is the dominant operational cost and it is entirely ours. No release in ~5 years, no issue triage, no compatibility guarantee, no community safety net. A 2020 PHP codebase will emit deprecations on 8.1+ that escalate to hard failures on a PHP minor bump, so decide during the spike whether we are forking to fix them. Maintenance effort is low in absolute terms — the package is small enough to read in under an hour — but it is unbounded in duration unless we vendor the source into our repo with a named owner and a recurring allowance against Nova upgrades.

Support. There is no vendor to call. Internal operators will route sidebar complaints to whichever engineer owns Nova, and that engineer will be debugging a dependency nobody on the team wrote. The realistic support posture is: name an owner before install, define the escalation path (roll back to the pinned version, reimplement natively), and make clear that "the sidebar looks wrong" is a P2 with a known diagnosis path rather than a novel incident each time.

Scaling. The package scales fine on the axis that matters here — it is configuration-only, so adding the 30th or 40th resource costs a $group constant and a config ordering entry, no engineering. It scales badly on two other axes. First, group proliferation: if every team adds a group, the sidebar becomes a hierarchy that is navigable in principle and useless in practice; enforce a small, stable taxonomy by operator domain and prune single-resource groups. Second, localization: $group is a static string on a Resource, so translating labels is awkward. If the package reads labels from config, put __('nova.groups.billing') there and leave $group as a stable key; if it does not, accept canonical English and do not override $group per locale at runtime — that path leads to resources swapping groups mid-session.

Failure modes. Ranked by how much they cost us:

Mode Signal Cost Mitigation
Silent regression after Nova/PHP bump Menu renders but groups flatten or resources drop out High — surfaces weeks later as an operator complaint Exact version pin + render smoke test (assertSee('Billing')) in CI
Asset layer not loaded Resources render, headings stay flat, or doubled labels Low — cosmetic, obvious, one command to fix nova:publish, clear Nova's compiled-asset cache
Boot-time exception Admin panel down Medium — loud but total Spike on a throwaway branch first; never install directly on main
PHP 8.x deprecation escalation Warnings in log, later hard failures Medium — silent until a minor bump APP_DEBUG=true during spike; fork or pin PHP minor
Conflict with another menu/theme package Ordering loss, resources disappearing High — painful to bisect Install last, test with others disabled first
Empty group header from policy filtering Collapsible header with nothing under it Low — cosmetic, but erodes trust in the nav Verify a fully-hidden group disappears on its own; otherwise hide via config, don't add a second permission layer

The smoke test is the highest-value artifact here and it is deliberately crude:

public function test_grouped_resources_render(): void
{
    $this->actingAs(User::factory()->create(['is_admin' => true]))
         ->get('/nova')
         ->assertOk()
         ->assertSee('Billing')
         ->assertSee('Catalog');
}

It catches the two failure modes that actually bite: a boot-time exception that takes the whole admin panel down, and a silent flattening after an upgrade.

Ramp-up. Low for anyone already fluent in Nova. Reading the source plus the spike is half a day, mandatory rather than optional given zero dependents — we are the QA function. The native reimplementation on Nova 4+ is a day or two for a Laravel engineer familiar with NovaServiceProvider, and it eliminates the maintenance tail entirely, which makes it the cheaper long-term path on almost every timeline that extends past one quarter. Where ramp-up is genuinely expensive is debugging: bisecting menu conflicts and diagnosing flat-versus-vanished headings both require reading Nova's menu internals, so treat that as a named skill on the owning engineer rather than assumed knowledge.

Bottom line for the roadmap. The opportunity signal is low — this is convenience, not differentiation, and on Nova 4+ it is already native. Recommend against adopting it as a standing dependency. If sidebar IA is a validated operator pain point, run it as a short prototype to generate evidence, then land ~100 lines of Nova::mainMenu() that we own. If it is not a validated pain point, the correct action is to trim what the sidebar exposes rather than nest what it already has — cheaper, faster, and nobody has to own anything.

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