alexbowers/nova-multiple-dashboard
Laravel Nova package that lets you create multiple dashboards in a single Nova installation, each with its own cards and configuration. Assign dashboards to users or roles so different teams see the metrics relevant to them, and register new dashboards with minimal setup.
Read this first: the package is marked [DEPRECATED] and the repository is archived (last release 2019-05-31). It existed to fill a gap in early Nova (1.x/2.x) where /nova had exactly one dashboard. Nova 3.7+ shipped native multi-dashboard support, which is why this was abandoned. Use it only if you are maintaining a legacy Nova install; for anything new, use Nova's built-in dashboards.
Minimal install (legacy Nova only):
composer show alexbowers/nova-multiple-dashboard --all # confirm constraints first
composer require alexbowers/nova-multiple-dashboard
php artisan vendor:publish --provider="AlexBowers\MultipleDashboard\MultipleDashboardServiceProvider"
php artisan migrate
If you're on Laravel < 5.5, register the published provider in config/app.php manually. Then clear caches (php artisan config:clear route:clear view:clear) before assuming it's broken.
Where to look first, in this order:
composer.json of the package — pin the exact Nova/Laravel versions it accepts; this is the single biggest source of "it doesn't work."dashboards table, pivot/user assignment, ordering column). Everything else follows from that shape.php artisan route:list --path=nova — confirm the dashboard route was actually replaced and what URI/name it uses.First use case: replace the single /nova landing page with one dashboard per team or role (Sales, Support, Ops), each with its own card set, and make each group land on their own board after login.
Define dashboards as data, not clicks. Create them in a seeder or migration so every environment (local, staging, prod) matches. Never rely on someone hand-creating rows in production.
// database/seeders/DashboardSeeder.php
Dashboard::updateOrCreate(
['slug' => 'sales'],
['name' => 'Sales', 'order' => 1]
);
Map cards to dashboards in one place. The package stores/derives the card list per dashboard; keep that mapping in a single service provider method or config array rather than scattering conditions across cards. A practical shape:
// NovaServiceProvider or a dedicated DashboardCards class
protected function cardsFor(string $slug): array
{
return match ($slug) {
'sales' => [new TotalSales, new PipelineValue],
'support' => [new OpenTickets, new CsatScore],
default => [new Help,
],
};
}
Gate visibility server-side. Hiding a dashboard from the nav is cosmetic. Enforce access with a Nova gate or policy so a user can't hit /nova/dashboards/{slug} directly:
Gate::define('viewDashboard', fn ($user, $dashboard) =>
$user->hasRole($dashboard->role) || $user->isAdmin()
);
Control the landing dashboard. The package's route override typically determines what /nova renders. Use it to redirect each user to their default board (/nova/dashboards/sales) rather than showing an empty shell. Keep the redirect logic in middleware so it survives package upgrades.
Per-tenant / per-role dashboards. Combine the dashboard slug with your tenancy scope: resolve the dashboard by (tenant_id, slug) and attach user assignments via the pivot table. This is the pattern that made the package attractive — replicate it deliberately rather than through ad-hoc card canSee() checks.
Cards that know their context. Custom cards can read the current dashboard from the request (request()->route('dashboard') or whatever param the package registers). Use that sparingly — cards that behave differently per dashboard are hard to test; prefer separate card classes per dashboard.
Link between boards. Add a small Nova menu/tool entry pointing at each dashboard slug so users can switch without editing the URL. Publish and override the package's views if it ships a nav partial.
Testing. Seed dashboards in setUp(), then assert GET /nova/dashboards/sales returns 200 for an authorized user and 403 for an unauthorized one. Do this before you touch Nova versions.
app/ under your own namespace (MIT license permits it) so you control it.nova.laravel.com repository. Expect composer update to break this package. Pin Nova in composer.json and treat Nova upgrades as a deliberate project.route:list --path=nova and click through every dashboard.config:clear, route:clear, view:clear, and composer dump-autoload are step one of any debugging. Published views in resources/views/vendor/... are especially easy to forget.canSee() are still reachable by direct request unless a gate or policy enforces access. Audit every route the package adds.NovaServiceProvider::cards() and per-dashboard. Centralize registration.php artisan nova:dashboard Sales.cards() method.NovaServiceProvider::dashboards() (or config/nova.php, depending on version).authorize() on the dashboard class./nova/dashboards/{slug} links.route:list) → caches cleared → user authorized via gate → card classes resolvable (app()->make(...)). Ninety percent of issues land in the first four.Bottom line: treat this package as a migration source, not a dependency. Copy the schema and access-control ideas into Nova's native dashboard classes, then delete it.
How can I help you explore Laravel packages today?