alexbowers/nova-categorise-resources
A Laravel Nova package that lets you categorise resources into labelled groups in the Nova sidebar. Keep large admin panels tidy by organising related resources under custom headings for faster, more intuitive navigation.
Before anything else, check your Nova version. This package is deprecated — Nova 1.0.18 and later ship native resource grouping via a public static $group = '...' property on each Resource class. If you're on Nova >= 1.0.18, you should not install this package; use the built-in $group property instead. Only reach for alexbowers/nova-categorise-resources if you're pinned to an old Nova release (< 1.0.18) and cannot upgrade.
Minimal steps for a legacy install:
composer require alexbowers/nova-categorise-resourcesphp artisan vendor:publish --provider="Alexbowers\NovaCategoriseResources\...") — the README will name the exact provider string.app/Providers/NovaServiceProvider.php or your nova/ config to confirm the package is wired in.UserResource) so you can eyeball the sidebar change without a full rebuild.First use case: take a messy flat sidebar of 15 resources and bucket them into 3–4 headings (e.g., "Content", "Commerce", "Settings") so admins stop scrolling. Do this on a single page load before touching every resource — collapse behaviour on a small group first confirms the package is working.
Group at the Resource level, not globally. The idiomatic use is a per-Resource declaration so each class owns its own categorisation. Depending on the package version this is either a $category / $group public static on the Resource, or a method like public static function category(): string. Follow whatever the README shows — do not mix conventions across resources, or you'll get resources that silently fall into an "Other" bucket.
Centralise the category names. Don't hardcode string literals in 20 Resource classes. Define constants in one place (a small ResourceGroups class or an enum-ish class) and reference them. This makes renaming a category a one-line change and prevents the typo-driven "two headings with almost the same name" problem.
// app/Nova/ResourceGroups.php
final class ResourceGroups
{
public const CONTENT = 'Content';
public const COMMERCE = 'Commerce';
public const SETTINGS = 'Settings';
}
// app/Nova/PostResource.php
public static $category = ResourceGroups::CONTENT;
Collapse-by-default for noisy groups. The package's collapsing feature is best used on groups admins rarely touch (Settings, Logs, Integrations). Keep high-traffic groups (Orders, Users) expanded so the common workflow isn't a click away.
Ordering is stable, not alphabetical. Categories typically render in the order they're first encountered at boot, which follows NovaServiceProvider::resources() registration order. If you want a deterministic order, register resources grouped by category in that method, or use the package's ordering hook if it exposes one. Don't rely on alphabetical ordering — the package doesn't sort by label.
Integration with NovaServiceProvider. Group your resources([...]) and resources() calls by category in the provider. This makes the sidebar intent visible in one file and gives you a natural place to add/remove whole categories.
Pair with policies, not categories. Categorisation is purely cosmetic. If a resource should be hidden from certain users, use canSee / policies — categories do not enforce access.
Migrating off the package (highly likely): if you're upgrading Nova, replace $category (or whatever property the package reads) with the native public static $group. The rendered result is equivalent, so this is usually a mechanical find-and-replace. Remove the package from composer.json after the swap and delete the config publish.
$group migration at the same time as the Nova bump.$group; this package may expect $category. If you set the wrong one, the sidebar won't change and you'll spend an hour wondering why. Confirm the exact property name in the README for the version you installed.NovaServiceProvider, or the package isn't booted. Check NovaServiceProvider::resources() first, then the property name, then package registration.NovaServiceProvider.php artisan optimize:clear and a hard browser refresh are the fastest way to see property changes reflected. Sidebar changes are often invisible until a full reload.composer.json (e.g., an exact version rather than ^) — an unbounded constraint against an abandoned package is asking for a resolver surprise.How can I help you explore Laravel packages today?