norman-huth/nova-resource-card
Laravel Nova Resource Card lets you display Nova resources as compact, customizable dashboard cards. Surface key records and resource data at a glance, making it easy to add quick-access resource overviews to your Nova dashboards.
Install
composer require norman-huth/nova-resource-card
Nova itself lives behind nova.laravel.com, so your Composer auth for nova.laravel.com must already be configured — this package pulls against your existing Nova install, not a public satellite.
Because the package is archived (last release 2024-03-08), do not use ^ constraints blindly. Pin it:
"norman-huth/nova-resource-card": "1.0.0"
Where to look first
vendor/norman-huth/nova-resource-card/src/ — the Card class. Confirm the exact namespace (it follows the author's Muetze42/NormanHuth convention) and the fluent setters exposed on the card before writing dashboard code.vendor/norman-huth/nova-resource-card/dist/ — check for a prebuilt js/card.js. If it exists, you never need Node; if not, you're in for a build.config/ file — determine whether options are config-driven or fluent-method driven. This decides your whole integration style.First use case
The canonical win is a dashboard that replaces a bare "Resources" sidebar with tappable cards showing each resource's name, icon, and record count — useful when non-technical admins live in Nova. Register it in your NovaServiceProvider:
// app/Providers/NovaServiceProvider.php
use NormanHuth\NovaResourceCard\ResourceCard; // verify namespace in src/
public function cards()
{
return [
ResourceCard::make()->resource(\App\Nova\User::class),
ResourceCard::make()->resource(\App\Nova\Order::class),
];
}
Or, for a single multi-resource card, pass an array of resource classes. Confirm the accepted signature in the card's constructor/fluent methods — this package predates any Nova 5 card conventions and its API is not guaranteed to match Laravel Nova's own Metric/Value ergonomics.
One card per resource, ordered deliberately. Register cards in the order you want them to appear; Nova renders in registration order, and card width controls grid flow. This is the most predictable pattern and keeps each card independently authorizable.
Multi-resource summary card. If the card accepts an array of resource classes, use it on a "home" dashboard for an at-a-glance admin view, and keep per-resource cards out. Mixing both produces duplicate counts and confuses users about which is authoritative.
Per-dashboard placement. Rather than globally in NovaServiceProvider::cards(), scope cards to dashboards where they earn their space:
// app/Nova/Dashboards/Main.php
public function cards()
{
return [
ResourceCard::make()->resource(\App\Nova\Order::class)->width('1/3'),
ResourceCard::make()->resource(\App\Nova\Customer::class)->width('1/3'),
];
}
Nova's width('1/3' | '1/2' | 'full') is applied by the card wrapper, so it should work regardless of the package's internals — verify visually.
Authorization is your job, not the card's. Wrap each card in canSee() so a user who cannot viewAny a resource never sees its count:
ResourceCard::make()
->resource(\App\Nova\Order::class)
->canSee(fn ($request) => \App\Nova\Order::authorizable()
&& \App\Nova\Order::availableForNavigation($request)
&& \Gate::forUser($request->user())->allows('viewAny', \App\Models\Order::class)),
Cache the counts. Aggregate counts on large tables are expensive, and Nova cards re-request on every dashboard load. Nova cards inherit cacheFor(); if this package doesn't override it, call it in your registration:
ResourceCard::make()
->resource(\App\Nova\Order::class)
->cacheFor(now()->addMinutes(10)),
If cacheFor() is a no-op here (possible, given the card is custom-built), cache at the query level with Cache::remember() inside whatever callback the card exposes.
Compose with metrics rather than duplicating them. Use a resource card for "where do I go" navigation and a Value/Partition metric for "how am I doing" trend data. Do not use a resource card to display a growth percentage it wasn't built to compute.
Fork-and-vendor for anything non-trivial. With 6 stars and 0 dependents, upstream fixes are not coming. If you need a behavior change, publish the card's views/assets (if the provider supports publishes()) or point Composer at your fork:
"repositories": [
{ "type": "vcs", "url": "[email protected]:yourorg/nova-resource-card.git" }
]
Remember the fork must keep the same package name in its composer.json for a drop-in swap.
Archived status is the headline risk. There will be no fix for a Nova 5 breaking change or a Vue 3 / Vite incompatibility. Before adopting, smoke-test the card in a staging Nova install; if the dashboard card silently renders blank, you are almost certainly hitting a Nova version mismatch, not a bug in your registration code.
Blank card = asset or prop problem. Debug in this order: (1) browser console for a missing card.js 404, (2) php artisan nova:publish if the package publishes assets, (3) vue devtools — inspect the card prop Nova hands the component and confirm the resource class and count are present. If the prop is there but the UI is empty, it's a Vue/build issue, not a PHP one.
Counts can leak data. A card that renders Order::count() regardless of policy exposes record volume to users who can't see the resource. Always gate with canSee(). This is the single most likely security mistake with any resource-count card.
Check whether the count respects your global scopes and Nova lenses. Resource::indexQuery() vs. Model::count() vs. Resource::applyFilters() produce very different numbers for soft-deleted, tenanted, or team-scoped models. Verify the number against what the resource index actually shows for the same user; if it diverges, don't ship it.
Soft deletes and withTrashed. A count taken from the Eloquent model silently excludes trashed records. If admins expect "all orders," that mismatch will be reported as a bug within a week.
Nova indexQuery overrides are not applied automatically. If your Order resource overrides indexQuery() for multi-tenancy, a card counting through the model will leak cross-tenant totals. Prefer counts derived from the resource's own query path if the package exposes one.
Dark mode and CSS. Hand-built Nova cards frequently hardcode colors. If the card looks wrong in dark mode, add a small CSS override in Nova::style() or your app's nova.css rather than editing vendor files.
Config is likely global, not per-card. If the package ships a config file, options may apply to every card instance. In that case, prefer multiple dashboards over multiple configurations.
Extension points to look for: publishes() for views/assets, a config/nova-resource-card.php, fluent ->icon() / ->label() / ->uriKey() setters, and the Vue component's props. The Vue layer is where almost all customization actually lives — treat the PHP class as a thin prop builder.
Publish before you patch. Run php artisan vendor:publish --provider="NormanHuth\NovaResourceCard\ResourceCardServiceProvider" (adjust the namespace) to see exactly what's overridable. If nothing publishes, your only stable extension path is a fork.
Upgrade discipline. Because there are no future releases, document the commit hash or version you pinned in your README, and add the card to your dependency-audit list. When you eventually upgrade Nova, this package is the first suspect for a broken dashboard.
How can I help you explore Laravel packages today?