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 Scheduled Jobs Laravel Package

llaski/nova-scheduled-jobs

A Laravel Nova package that brings your scheduled tasks into the Nova dashboard. View every scheduled job, inspect cron expressions and next run times, run jobs manually, and toggle them on or off without leaving your admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a Nova tool, not a library — it renders Laravel's Schedule singleton as a table inside your existing Nova admin panel. Treat it as a live inventory of registered jobs, not as monitoring.

Minimal install (two steps, no migrations):

composer require llaski/nova-scheduled-jobs
// app/Nova/NovaServiceProvider.php
use Llaski\NovaScheduledJobs\NovaScheduledJobs;

public function tools()
{
    return [
        new NovaScheduledJobs(),
    ];
}

Then open Nova → Scheduled Jobs. There is no config to write, no asset compile step, and no write path to your database. Backing it out is deleting the line and running composer remove.

Where to look first:

  1. composer.json at the installed tag — check the laravel/nova and illuminate/* constraints against your stack. The 6.1.3 line was tagged August 2023; Nova 5 / Laravel 11+ is unverified, so prove it on staging before it lands on a shared admin.
  2. app/Nova/NovaServiceProvider.php — confirm the tool is registered exactly once.
  3. Wherever your schedule is defined: app/Console/Kernel.php on Laravel ≤10, routes/console.php or bootstrap/app.php on Laravel 11+.

First use case: put the Nova page and php artisan schedule:list side by side on your first deploy. They should show the same set of jobs. If they disagree, you have a registration-context problem (the schedule isn't loaded on web requests), not a rendering bug — and that distinction is the single most useful debugging habit with this package. From there, the daily use is answering "is the nightly job still scheduled, and when does it next fire?" without SSH.

Implementation Patterns

Name every closure. The table renders each event's description or command string. An unnamed Schedule::call() is an opaque row that helps nobody:

$schedule->call(fn () => SearchIndex::rebuild())
    ->dailyAt('02:00')
    ->name('Rebuild search index')
    ->description('Nightly full reindex — runs on one server')
    ->onOneServer()
    ->withoutOverlapping();

Keep one source of truth. Register the schedule in one place so the tool reads the same singleton your console kernel does. Duplicating Schedule:: calls across providers or a package's service provider produces duplicate rows, which read like a package bug but are a registration bug.

Restrict visibility with canSee(). The tool is visible to every Nova user by default, and cron internals are operational detail most users don't need:

public function tools()
{
    return [
        (new NovaScheduledJobs())->canSee(
            fn ($request) => $request->user()->isAdmin()
        ),
    ];
}

Annotate guardrails in descriptions. The package does not surface withoutOverlapping(), onOneServer(), or runInBackground() — a guarded job looks identical to an unguarded one. If the team needs to know a job is single-server or non-overlapping, put it in ->description() where people will actually read it.

Use it as a triage tool, paired with the CLI. The workflow that pays for itself: a report of "the nightly export didn't run" → open the Nova page to confirm the job is still registered and see its next run → php artisan schedule:list to confirm the same from the CLI → Horizon/failed-jobs/logs for whether it actually executed. The package answers registration questions only; success and failure live elsewhere.

Add it to the deploy runbook. One line — "verify the Scheduled Jobs page after deploy" — catches jobs whose registration silently moved between Kernel.php, a service provider, and routes/console.php, or whose cron expression drifted during a refactor. This is cheap and catches real regressions.

Extend with a separate card, not by fighting the tool. If you need last-run times, exit codes, or runtime, don't try to add columns to a read-only Vue table. Add a schedule_runs table written from a Schedule::after() hook (or a queued event listener) and surface it in your own Nova metric or card. Keep the package's job narrow.

Scope it per environment. On staging and production it earns its place; on a local dev dashboard it's clutter. Gate it with canSee() by environment or role rather than maintaining a fork.

Gotchas and Tips

  • Unnamed closures render as generic rows. Schedule::call(fn () => ...) with no ->name() gives you a row you can't identify. Fix the schedule definition, not the package.
  • Empty page on Laravel 11+. The scheduler is populated during console bootstrap. Laravel 11 moved definitions to routes/console.php / bootstrap/app.php; if the web request never loads them, the Nova page renders empty. Diagnose in one command: if php artisan schedule:list shows the job and the page doesn't, it's a bootstrapping issue. Move definitions to a provider that boots on every request.
  • Timezone drift in next-run times. Next-run is computed from the cron expression; a job with ->timezone('America/New_York') can disagree with what you expect from config('app.timezone'). Before filing a bug, compare against schedule:list and the server's date.
  • No execution history — ever. This page cannot answer "did it run?" or "did it fail?". Mutexes, exit codes, and last-run results aren't represented. Do not let anyone start treating it as alerting.
  • Duplicate rows mean duplicate registration. Grep app/, routes/console.php, and every package service provider for repeated Schedule:: calls before blaming the package.
  • Stale sidebar entry after registering. Nova caches menus and tools per session. If the tool doesn't appear, refresh the browser before you start re-reading your service provider.
  • Pin the version and plan an exit. Single maintainer, 54 stars, no release since August 2023. Pin to an exact version, re-verify on every Nova/Laravel upgrade in staging, and accept that forking is realistic. The fork is small and contained: the data is just Schedule::events(), so a replacement Nova tool that renders the same collection is a short job if the package goes stale.
  • Authorization is on you. The route sits behind Nova's auth middleware, but every Nova user sees it by default. canSee() or a Nova policy is the fix, not a package setting.
  • Debug with the CLI first, always. php artisan schedule:list cleanly separates "the job isn't registered" from "the page isn't rendering it". Reaching for the browser devtools before running that command wastes time.
  • Extension points are shallow. Expect a read-only Vue table with no supported column API. For anything beyond inspection, build alongside it rather than patching it — that keeps the dependency disposable.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource