stepanenko3/nova-health
Nova Health is a Laravel Nova package that brings application health checks into your admin panel. It displays health check statuses and results in Nova, giving teams a quick, centralized way to monitor app health and spot issues without leaving the dashboard.
Install against your actual Nova version, not the latest tag. Check the constraint first:
composer show stepanenko3/nova-health --all
Read the declared laravel/framework, laravel/nova, and PHP ranges before you commit. With 13 stars and zero dependents, that composer.json is the only compatibility contract that exists — there is no ecosystem of people who have already hit the upgrade you are about to hit.
Two-line install, no migrations. There is no data model, so there is nothing to migrate and nothing to back up:
composer require stepanenko3/nova-health
Register the tool in app/Nova/NovaServiceProvider.php (or app/Providers/NovaServiceProvider.php on older skeletons):
public function tools()
{
return [
// ...existing tools
new \Stepanenko3\NovaHealth\NovaHealth,
];
}
Publish the config by picking from the list, not by guessing a tag. php artisan vendor:publish with no tag and choosing the nova-health entry is faster than fishing the tag name out of the README:
php artisan vendor:publish
The published config is the real documentation. It tells you which checks ship enabled, whether they are self-contained or delegate to something like spatie/laravel-health or your /up route, and how timeouts are expressed.
Read src/ for five minutes before you click anything in the browser. Four questions determine your entire maintenance budget:
canSee() / authorize() and what does it return by default?Gate it before you look at it. Add the gate in the same PR as the install, not after:
// NovaServiceProvider::boot()
Gate::define('viewHealth', fn ($user) => $user->hasRole('ops'));
and override canSee() on the tool to consult it. Health output leaks DSN shapes, disk paths, queue depths, and which of your services are reachable — that is reconnaissance data if it is broadly visible.
First use case: break something on purpose in staging. Open the panel green once, then stop the queue worker or point a cache check at a dead Redis port and reload. A health dashboard you have only ever seen green is untested; you do not know what its failure rendering looks like, whether a timeout maps to "fail" or silently to "pass," or whether the empty state is distinguishable from the healthy state.
Treat the Nova panel as a second surface over checks you already run. If you have a /up endpoint, a Kubernetes readiness probe, or spatie/laravel-health, do not reimplement the same probes inside the Nova tool. Point both surfaces at the same underlying check so the dashboard an operator glances at and the path that actually pages someone can never disagree. The Nova UI is the convenience layer; alerting stays where it is.
Cache every network-bound custom check. Any check that leaves the process — S3 head request, third-party API ping, Stripe key sanity check — goes behind a short cache:
return Cache::remember('health:payments-api', now()->addSeconds(60), function () {
// Http::timeout(2)->get(...)
});
Without this you have "N probes per page load per viewer." Five ops people refreshing during an incident multiplies your outbound traffic fivefold and can turn a degraded dependency into a rate-limited one. Sixty seconds is enough to make refreshes free.
Always set an explicit timeout on outbound checks. If checks run synchronously in the tool's request (question 3 above), an unbounded HTTP call is an unbounded page load. A health screen that hangs during a partial outage is worse than no screen, because it also burns the operator's time and erodes trust in the panel.
Scope custom checks to services whose failure changes your triage. Adding a marketing API ping feels thorough until it flakes and paints the whole panel red. Operators who learn that red is noise stop reading red. Reserve checks for things where "this is down" actually means "go do something."
Confirm red states with a throwaway always-fail check. Implement a check that returns failure unconditionally, load the page once, screenshot it, delete it. This is the cheapest way to verify failure rendering, color coding, and — critically — whether exceptions and timeouts land in the fail bucket or get swallowed.
Keep deploy gating out of Nova. Post-deploy smoke checks belong in CI as curl -f https://app.test/up, in the step that can actually fail a pipeline and block a bad release. Nova Health does not block anything; wiring a flaky check into a deploy gate so that it blocks a rollback is an own-goal. Use it for human triage and post-deploy eyeballing.
Pin the exact version and treat bumps as deliberate events. Tie any bump to a Nova major upgrade you were already doing, so that when the panel breaks you have exactly one variable to suspect instead of two. Add "does the health page render after deploy" to the Nova upgrade checklist — Nova itself will stay up even if the tool's compiled Vue bundle is stale, so nothing else will alert you.
Removal is genuinely cheap — keep it that way. composer remove stepanenko3/nova-health, delete the Nova::tools entry, clean out the published config and any compiled assets. The reversibility is the main argument for trialing this instead of building a health screen; preserve it by not growing custom checks that outlive the tool.
A timeout that returns "pass" is the failure mode that actually matters. Read the check implementations and find out what happens on an exception or a timeout. Silent success converts "we don't know" into "we checked and it's fine" — strictly worse than having no dashboard at all. This is the single most important thing to verify before you trust the panel.
Per-process blindness behind a load balancer. Health is a property of the process that served your request. Six nodes behind an ALB and this panel truthfully reports one of them. During a partial outage you will see a green dashboard and red customers. Keep an external prober and treat this as one sample, never as the fleet's status.
Assume the default canSee is permissive until you have read it. Community Nova tools frequently default to "any authenticated Nova user." Confirm in code — do not infer it from a screenshot of your own admin account.
A blank panel with a 200 is an asset problem; a blank panel with a 500 is a check throwing. Find the endpoint first:
php artisan route:list | grep -i health
Hit it directly with an authenticated session and watch the Network tab and storage/logs/laravel.log. That split saves you an hour of guessing.
Compiled assets may not match your Nova version. If the bundle looks stale, rebuilding from source requires Nova's frontend dev tooling installed locally. Budget that before adoption, and write it down — the next person to touch this will not know it either.
Rebuilding assets is the fork-likely scenario, so document the fork now. MIT license, single maintainer, last release February 2025, bus factor of one. Identify one engineer comfortable with Nova tool internals and write down how you would fork and patch it while that is still a thought experiment rather than a Friday-night incident. The most probable patch you will ever need is a one-line asset or constraint fix — the second most probable is a timeout/exception handling change in a check.
Do not let it drift into being your monitoring. This package will not page anyone, has no history, and no SLOs. If you want trend lines, alerting, or tracing, that is Laravel Pulse, Sentry, or a managed uptime service. Nova Health is a triage convenience for people already in the admin panel — write that scope down so a pilot does not quietly become the source of truth.
How can I help you explore Laravel packages today?