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 Info Card Laravel Package

pdmfc/nova-info-card

A Laravel Nova card for surfacing informational content on your dashboard or resource screens. Add a custom info panel to display key metrics, notices, or contextual guidance alongside your other Nova tools, keeping important details visible where your team needs them.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the card package into a Nova-enabled Laravel app:

composer require pdmfc/nova-cards

There is normally nothing to publish — Nova auto-registers the card's compiled assets. If the card renders as an empty box after install/upgrade, run php artisan nova:publish and clear caches (see Gotchas).

Where to look first

  1. vendor/pdmfc/nova-cards/src/ — the PHP card classes. After v1.0 the generic card is Pdmfc\NovaCards\Info (it was previously Pdmfc\NovaCards\Card). Sibling classes follow the same namespacing for the other themes (Success, Warning, Danger).
  2. vendor/pdmfc/nova-cards/resources/js/ — the Vue component, if you need to confirm which fluent setter maps to which template slot.
  3. The README, which was updated in v1.0 and is now the fastest reference for the fluent API.

First use case — show an informational banner on a resource's detail screen:

use Pdmfc\NovaCards\Info;
use Laravel\Nova\Http\Requests\NovaRequest;

public function cards(NovaRequest $request): array
{
    return [
        (new Info)
            ->text('Staging environment')
            ->body('Changes here are not customer-visible.'),
    ];
}

Two things to internalise immediately:

  • The class rename to Pdmfc\NovaCards\Info is a breaking change. Any v0.x code using Pdmfc\NovaCards\Card must update its use statement.
  • v1.0 renders raw HTML in the message body, so <a>, <strong>, <br> now work instead of being printed as literal text. That is the feature most day-to-day value comes from — and the one that needs a security habit attached to it.

Implementation Patterns

Treat cards as a presentation layer over a small query. The most common real usage is "surface a number or status the resource page doesn't otherwise show":

public function cards(NovaRequest $request): array
{
    $pending = Order::where('status', 'pending')->count();

    return [
        (new Info)
            ->text('Order queue')
            ->body("{$pending} orders awaiting fulfilment.")
            ->width('1/2'),
    ];
}

Because cards() is evaluated on each resource request, wrap anything non-trivial in Cache::remember() — a card is not worth an N+1 on every detail page load.

Choose the theme semantically. Reach for Danger for states that need action (failed sync, expired credentials), Warning for degraded-but-working, Info for context, Success for confirmation. v1.0 added a proper icon for the danger theme, so it now reads correctly at a glance rather than looking like an unstyled Info card.

Use raw HTML for links, not for layout. The v1.0 HTML support is best spent on anchors and inline emphasis:

(new Warning)->text('Maintenance window')
    ->body('Read the <a href="https://wiki.example.com/runbook" target="_blank">runbook</a> before deploying.');

For anything longer than a sentence or two, render a Blade partial to a string instead of concatenating HTML in PHP:

$html = view('nova.cards.runbook', ['step' => $step])->render();

(new Info)->text('Runbook')->body($html);

That keeps markup diffable and lets you {{ }}-escape interpolated values for free.

Register cards at the right scope.

  • Resource cards → cards() on the Resource class (detail/index of that resource only).
  • Global cards → NovaServiceProvider::cards() or Nova::cards(), visible everywhere.
  • Dashboard cards → the dashboard's cards() method.

Scope matters: a "billing is down" banner belongs globally; a "this order is refunded" card belongs on the resource.

Branch on detail vs index using the request, since the same cards() method serves both:

if ($request->resourceId === null) {
    return []; // index view — keep it clean
}

Gate with canSee() rather than conditional array building, so the intent is declarative:

(new Danger)->text('Impersonating')
    ->canSee(fn ($request) => $request->user()->isAdmin())

Test it cheaply. Assert on the array returned by cards() — class, and the output of the fluent getters — instead of doing browser assertions on a Nova screen.

Gotchas and Tips

The v1.0 rename will bite you silently. Pdmfc\NovaCards\Card → Pdmfc\NovaCards\Info. A stale import produces a "class not found" at runtime, not at install time, so grep your codebase for NovaCards\Card before bumping. Pin "pdmfc/nova-cards": "^1.0" if you support older Nova apps that can't take the rename yet.

Raw HTML changes the escaping contract. Anything you route into body() from user input, model attributes, or third-party APIs is now an XSS vector. Escape explicitly (e($value), or {{ }} inside a rendered view) and only pass trusted markup raw. This is the single most important behavioural difference from pre-1.0 and it won't produce an error — just a vulnerability.

Card not appearing / stale UI after upgrade. Nova compiles a component manifest and the browser caches the JS bundle. In order: php artisan nova:publish --force, php artisan view:clear, php artisan config:clear, then a hard refresh. If the card renders but looks like the old version (missing danger icon), it's almost always a cached bundle, not a broken release.

Icons and spacing changed for danger. Cosmetic-only, but if you had CSS or a screenshot test asserting on the card's layout, expect a diff.

Fluid API is not validated for you. Cards are permissive about ordering (text() before or after body()); an empty body() typically renders an empty slot rather than erroring, so a card that "doesn't show the message" is usually a setter you forgot to call. Dump the card instance in cards() to confirm what you built.

Extension points. Subclassing a card class is the cheapest customisation — override the component property or the fluent defaults. Deeper visual changes mean either publishing the package's Vue assets or writing your own card; forking the JS for a colour tweak is rarely worth it when the four built-in themes already map to Nova's palette.

Check Nova version compatibility in composer.json of the package before upgrading in a lockfile-heavy project. Nova major upgrades are the usual reason card packages break, and it will show up as a Vue render failure with no useful PHP stack trace — check the browser console first when debugging.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle