Product Decisions This Supports
- Whether the internal admin becomes a real ops dashboard, or stays a CRUD screen. Nova Bar Metrics adds bar-chart metric cards to Laravel Nova dashboards, aimed squarely at frequency distributions — "tickets by status," "orders by value bucket," "signups by plan tier," "moderation actions by reason code." That answers "what does the shape of the work look like right now?" It does not answer "how has this moved over time?" — that is Nova's native Trend card. Keep those two questions separate when scoping the roadmap item; conflating them is how a one-sprint card turns into an open-ended analytics project.
- Build vs. buy for admin analytics. Nova ships Trend, Value, Partition (pie/donut), and Progress cards. A plain categorical bar chart is a genuine gap in that lineup — horizontal bars read category comparisons better than a pie once you have more than ~5 slices. This package is a candidate "buy," but the entire capability is a few hundred lines of a custom Nova card, which puts a very low ceiling on what "buy" should be allowed to cost in money, risk, or maintenance burden.
- Sequencing against a BI purchase. If the live question is "do we buy Metabase/Looker, or extend the admin panel we already pay for?" — this package is evidence for the cheaper path, provided the requirement is static internal counts. It is not evidence for the BI path (drill-down, ad-hoc filtering, export, cross-period comparison). Do not let a polished demo of a bar card stand in for that evaluation; it will make the BI case look weaker than it is and the in-house case look stronger than it is.
- Feature-level fit. Fits well: support queue triage by category, sales distribution by deal size, moderation counts by reason code, cohort counts by plan. Does not fit: click-through to filtered resource lists, CSV export, date-range pickers, period-over-period comparisons. Promise those separately or they will be assumed in the demo and missed at launch.
- Roadmap sizing signal. The realistic delivery is "fork, verify, and own" — roughly a day of engineering for the card itself, plus ongoing first-party ownership. That is cheap enough to slot into a maintenance sprint, and expensive enough that it should not be sold as "free."
When to Consider This Package
Consider it only when all of these hold:
- You are on a legacy Nova install (1.x/2.x) with a matching Laravel/PHP baseline, and need a bar card this sprint with no front-end design work.
- The chart is internal-only, read by staff, and a broken or stale card is an annoyance rather than a customer-facing outage.
- You have someone who can read and patch both the Vue component and the metric class — because you, not the publisher, will be the maintainer from day one.
- You have verified it actually renders on your Nova version in a throwaway spike branch, before it enters a roadmap or a stakeholder commitment.
- The metric is not decision-critical — nobody is making a budget, headcount, or pricing call off an unmaintained card.
Look elsewhere when:
- You are on Nova 3, 4, or 5 — assume incompatibility until proven otherwise. Nova 4+ moved to Inertia + Vue 3 with a revised asset and tool-registration pipeline; a 2018 Mix/Vue 2 build will not load unmodified. Budget this as a rewrite, not a patch.
- You are on PHP 8.x / Laravel 9+ — expect Composer to refuse resolution against the package's
laravel/nova and php constraints, and expect dynamic-property and missing-return-type notices once you widen them.
- You need a maintained dependency with a security response channel. A seven-year-old single-maintainer repo with 40 stars and zero dependents offers neither, and Nova's commercial support does not extend to third-party tools. This is a real risk-acceptance decision, not a footnote.
- The requirement is expressible with native metrics — a categorical frequency is often a
Partition card, or a stacked Trend with ->showValues(). If so, close the evaluation and add no dependency surface at all.
- You need anything beyond static bars: filtering, click-through, export, period comparison — or the requirement is really a purpose-built analytics page rather than a dashboard card.
Rule of thumb: budget adoption as "fork and own," never "composer require and forget." If fork-and-verify exceeds roughly a day of engineering, build the card in-house against your actual Nova version — same pixels, a support path you control, and no orphaned entry in the SBOM.
How to Pitch It (Stakeholders)
To executives (one paragraph): We can add frequency-distribution bar charts to our internal Nova admin panel, giving ops and support leads a quick read on how work is distributed — tickets by status, orders by size, users by plan — without buying a BI license. The specific open-source package that does this is unmaintained (last release 2018), so the honest recommendation is not "install it" but "build a small first-party card, optionally borrowing this code under MIT." That is roughly a day of engineering plus ongoing ownership in a codebase we already run, and it either closes the near-term reporting gap cheaply or gives us concrete evidence about whether the real need is a BI tool. It does not replace a BI evaluation — it defers it responsibly.
To engineering (short): Treat insenseanalytics/nova-bar-metrics as a reference implementation, not a dependency. The useful assets are the pattern (one Metric subclass returning a label→value array, one small Vue card rendering Chart.js bars) and the accumulated gotchas: do binning in SQL with a CASE expression, force bucket ordering in PHP, insert zero-count buckets explicitly or the chart silently misleads, COALESCE NULL categories into an "Unknown" bucket, cache with cacheFor() and add an index on the grouped column, and put authorization on the metric via canSee() rather than on the dashboard. Preserve the MIT attribution in the file header. Minimum test coverage: one assertion on exact bucket output against a seeded fixture, one asserting empty buckets are present, one snapshot of the rendered card. Two things to check before anyone commits: what the native Partition card already gives us, and whether a stacked Trend with ->showValues() satisfies the requirement with zero new code.