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

beyondcode/nova-laravel-update-card

A Laravel Nova card that displays your app's installed Laravel version alongside the latest release, flagging available framework updates at a glance so you can keep dependencies current and plan upgrades right from your Nova dashboard.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install anything, answer one question: what Nova major are you on? This card’s only release is 0.0.1 (2018-08-22) and the repo is archived. It was compiled against Nova 1.x/Vue 2. Nova 4+ ships Vue 3, and a 2018-era dist/js/card.js will not mount — you get a blank card and a silent console error, not a helpful failure. If you’re not on Nova 1.x, read this package as reference material, not a dependency.

Step 1 — Reconnaissance spike (throwaway app only). Never try this first in a shared install.

composer require beyondcode/nova-laravel-update-card:0.0.1 --dry-run

--dry-run is the whole point: it surfaces the constraint resolution before it touches your lockfile. If Composer wants to downgrade illuminate/* or PHP to satisfy a 2018 constraint, stop. That is the "this package becomes the reason we can't upgrade" failure mode, and it is far more expensive than the card is worth.

Step 2 — Register the card. In app/Providers/NovaServiceProvider.php:

public function cards()
{
    return [
        new \BeyondCode\LaravelUpdateCard\LaravelUpdateCard(),
    ];
}

If the card doesn’t appear, check auto-discovery in vendor/composer/installed.json, then php artisan nova:publish (asset registration in the 2018 era required published assets), then the browser network tab for a 404 on the card’s JS bundle.

Step 3 — Read the source first. Three files tell you everything:

  • src/LaravelUpdateCard.php — the card class; look at what ->withMeta() it pushes to the front end.
  • src/*ServiceProvider.php — the Nova::serving() closure, which is where Nova::script() registers the bundle.
  • dist/js/card.js — the compiled component; grep it for a URL to find out whether the version lookup happens in the browser or server-side.

That last question dominates everything: if the compiled JS calls Packagist or the GitHub API directly from the browser, you inherit CORS behaviour, per-IP rate limits, and an unauthenticated external call made by every admin’s browser session.

First real use case. The card answers exactly one question — "is laravel/framework behind latest stable?" — as a human-visible nudge on a dashboard someone actually looks at. It is not an upgrade process, not a CI gate, and not a dependency-drift monitor.

Implementation Patterns

Pattern 1: Assign it to a dashboard, not the default one

If you keep the card, scope it so it doesn’t clutter the main dashboard:

public function cards()
{
    return [
        (new \BeyondCode\LaravelUpdateCard\LaravelUpdateCard())
            ->onlyOnDashboards(['platform-health']),
    ];
}

onlyOnDashboards() / canSee() are Nova card APIs, so if they’ve changed, that is the first thing to check when the card renders everywhere or nowhere.

Pattern 2: Rebuild it as an owned card (the recommended path)

The feature is small enough that ownership wins. Generate a card with your current Nova version and reuse the package’s source as the spec:

php artisan nova:card acme/laravel-currency

Then keep the outbound call on the server, behind a cache, behind one adapter:

// app/Support/LatestLaravelVersion.php
class LatestLaravelVersion
{
    public function __invoke(): ?string
    {
        return Cache::remember('laravel:latest', now()->addHour(), function () {
            $res = Http::timeout(3)->retry(2, 200)
                ->get('https://repo.packagist.org/p2/laravel/framework.json');

            if ($res->failed()) {
                return null;
            }

            $versions = collect($res->json('packages.laravel/framework'))
                ->pluck('version')
                ->reject(fn ($v) => str_contains($v, 'dev') || str_contains($v, '-'))
                ->map(fn ($v) => ltrim($v, 'v'));

            return $versions->sort(fn ($a, $b) => version_compare($a, $b))->last();
        });
    }
}

The card itself becomes a thin renderer of two cached strings — installed vs. latest — with a last-checked timestamp. It never blocks a dashboard render on an HTTP call.

Pattern 3: Mirror the signal into CI

The card is for humans; the enforce-able version of the same fact belongs in a job:

composer outdated laravel/framework --direct --strict

--strict exits non-zero when anything is outdated, so it can fail a nightly job and open a ticket. This is the pattern that actually keeps the framework current; the dashboard card is the ambient reminder, and should never be the only signal.

Pattern 4: Wrap, don’t inline

If you do adopt the package as-is, put a single adapter class in front of whatever it calls and point a contract test at it:

it('resolves a latest laravel version', function () {
    $this->assertNotNull(app(LatestLaravelVersion::class)());
});

When the upstream endpoint changes shape, this fails in CI instead of silently rendering a stale green card for six months.

Pattern 5: Degrade to "unknown", not to stale

Design the failure state explicitly in your own card: if the lookup fails, show Unknown — last checked <time> in a neutral/warning style. A card that keeps showing yesterday’s cached "up to date" after a failed check is worse than no card, because people trust it.

Gotchas and Tips

  • Archived means permanent. No patch will arrive for a blank card, a broken endpoint, or an API change. Fork-and-fix is the only support path — and if you’re forking anyway, you’ve already paid the cost of building it.
  • Composer constraints are the real risk, not the UI. A 0.0.1 from 2018 resolved against PHP 7.x and illuminate/* of that era. Always --dry-run first, always exact-pin ("0.0.1", no caret) if you proceed, and never run composer update -W to force it.
  • Nova itself is paid and closed-source. Any CI environment that needs to boot Nova needs credentials for the nova.laravel.com Composer repository — including the contract test above. Budget for that before wiring the card into automated checks.
  • The asset pipeline is dead. Rebuilding dist/js/card.js means the package’s own package.json and webpack version from 2018; expect to nvm use 10 and fight it. This is the strongest argument for php artisan nova:card against current Nova instead.
  • Version comparison subtleties. version_compare handles 8.0.0-RC1 < 8.0.0 correctly, but you must strip a leading v, filter dev-* branch aliases, and decide whether you compare major.minor or full semver. Comparing 8.83.27 against latest 11.x is correct; comparing branch aliases is not.
  • It only sees laravel/framework. Not Symfony components, not Nova itself, not transitive dev tooling. Do not let a green card stand in for dependency management — pair it with composer outdated or a dependency bot.
  • It does not distinguish security patches from feature releases. A "you're 3 majors behind" prompt and a "there's a patch release" prompt are very different operational asks. Any internal rebuild should show the delta, not just a boolean.
  • Browser-side rate limits. If the compiled JS calls GitHub’s API, that’s 60 requests/hour per IP unauthenticated, shared across everyone behind your office NAT. Server-side + hourly cache removes this class of bug entirely.
  • Debugging checklist for a blank card: Nova version vs. Vue version → network tab for the JS bundle 404 → nova:publish → browser console for a mount error → the service provider’s Nova::serving() closure. The card class itself is almost never the problem.
  • Do not treat the green card as compliance evidence. It’s read-only, it doesn’t gate deploys, and it doesn’t notify anyone. If framework currency matters for security or EOL reasons, the forcing function has to be a scheduled job with an owner, not a widget.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core