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

interaction-design-foundation/nova-html-card

A Laravel Nova card that renders custom HTML or Blade content directly on your dashboards and resource pages. Drop in markup, embed views, and build flexible info panels without writing a full custom card component.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the card with Composer (no service provider registration, config publishing, or migrations are required):

composer require interaction-design-foundation/nova-html-card

The first place to look is vendor/interaction-design-foundation/nova-html-card/src/ — it is a single Nova Card subclass plus a compiled Vue component. Read that class and the README before wiring anything up; there is no configuration surface, so the only API you need is the content setter and Nova's inherited card methods (width, canSee, onlyOnDetail, etc.).

Register the card in your main dashboard via app/Providers/NovaServiceProvider.php:

use InteractionDesignFoundation\NovaHtmlCard\HtmlCard;

public function cards(): array
{
    return [
        (new HtmlCard)
            ->html('<h2>Team Docs</h2><p>Deploy runbook: <a href="https://wiki.example.com/deploy" target="_blank" rel="noopener">wiki</a></p>')
            ->width('full'),
    ];
}

That is the canonical first use case: a low-effort "inline docs" panel — onboarding links, a support banner, a checklist, or a pointer to runbooks — living directly on the Nova dashboard where operators already are. Reload /nova and the card should render before you touch anything else.

Implementation Patterns

Keep markup in Blade, not PHP strings. Long HTML literals are unmaintainable and quote-escaping becomes a hazard. Render a partial and hand the string to the card:

(new HtmlCard)
    ->html(view('nova.cards.quick-links', ['user' => request()->user()])->render())
    ->width('1/2'),

This also gives you Blade's @if, translations, and route() helpers for free.

Compose a dashboard from multiple small cards. Multiple HtmlCard instances with ->width('1/3'), '1/2', or 'full' let you build a grid of focused panels instead of one wall of text. Array order in cards() is display order, so treat that method as your layout.

Reuse the same card on resources and custom dashboards. Nova cards are generic, so the same class works in NovaServiceProvider::cards(), in a Dashboard class's cards(), and in a resource's cards(NovaRequest $request) method. Scope it with Nova's inherited helpers:

public function cards(NovaRequest $request): array
{
    return [
        (new HtmlCard)
            ->html(view('nova.cards.user-guide')->render())
            ->onlyOnDetail()
            ->canSee(fn ($request) => $request->user()->isAdmin()),
    ];
}

Make content dynamic but cheap. Pulling the current user, a config flag, or a cached settings row into the view is the natural extension point. If the content comes from the database, cache it — see the next section.

Treat Markdown as a content source. For prose-heavy docs, store Markdown and convert at render time (Str::markdown($content)) rather than hand-writing HTML. Sanitize anything not authored by you.

Gotchas and Tips

  • This is an XSS surface by design. The card injects raw HTML (typically through Vue's v-html), so it is not escaped. Never pass request input, user profiles, or database fields you don't control directly into ->html(). For anything dynamic, sanitize first (e.g. mews/purifier) or build markup in a Blade partial where escaping is explicit.
  • Blade escaping bites. {{ $value }} escapes; use {!! $value !!} only for trusted HTML. If the whole partial is HTML, view(...)->render() is cleaner than mixing escaped and unescaped output in one string.
  • Scripts and Vue bindings won't work. v-html does not execute <script> tags and does not compile directives. If you need interactivity, buttons, or data fetching, write a proper custom Nova card instead of trying to smuggle JavaScript through this one.
  • Check Nova version compatibility and pin it. The package has zero dependents and a small surface, which is good for blast radius but means fewer people exercising edge cases against your Nova major version. Constrain the version in composer.json and smoke-test after Nova upgrades.
  • Confirm the setter name for your tag. It is a tiny package; if ->html() doesn't exist on the installed release, check the README in vendor/ — the method is the only thing you need to get right, and the class is short enough to read in a minute.
  • Dark mode and styling. Nova ships light and dark themes. Hard-coded hex colors and backgrounds will look broken in one of them. Prefer Nova's utility classes or CSS variables, and test both themes before shipping. The card wrapper also adds padding and a border, so don't re-create a card frame inside your HTML.
  • Don't do work in the constructor. Cards are instantiated during Nova boot for every dashboard/resource request. Any query or expensive view render in cards() runs on each page load — cache aggressively or move logic into a cached view composer.
  • Debugging a blank card. The card's HTML is serialized into Nova's bootstrapped config JSON, so inspect the network response for /nova-api/... (or view source) to confirm your string is present. If it's present but not visible, the issue is CSS/width/Vue rendering, not PHP. If it's absent, your cards() method isn't being hit or canSee is returning false.
  • Use <details>/collapsibles for long docs. A card with 40 lines of text dominates the dashboard. Wrap verbose content in <details><summary>...</summary>...</details> or link out to a Nova page/resource instead.
  • External links need target="_blank" rel="noopener", and inline styles may be blocked by a strict Content-Security-Policy — if styles vanish in production but work locally, check CSP before blaming the package.
  • Extension point is the Blade partial, not the package. Don't fork the vendor JS to customize layout; keep all customization in your views and Nova card methods.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package