orchid/charts
Chart widgets for the Laravel Orchid admin platform, adding Chart.js-powered visualizations to screens and dashboards via simple layout fields.
Architecture fit. This is a presentation-layer convenience for internal admin screens, not a platform component. Its value is conditional on one thing: that we run (or are about to commit to) the Orchid Platform admin panel. Outside Orchid — Filament, Nova, a bespoke Blade app — the fit is effectively zero, and adopting it would be an implicit architectural vote for Orchid rather than a neutral tooling choice. Even inside Orchid, what we are buying is a reusable chart-as-a-class wrapper over data we already have as Eloquent results or arrays. That is roughly one to three developer-days of work we would otherwise write ourselves, so the ceiling on adoption effort is low by construction.
The identity problem is the first technical risk, and it precedes all others. Three sources disagree: the package metadata describes "server-side SVG charts, zero JavaScript runtime"; description.md describes interactive Chart.js visualizations; the v0.0.10 release notes describe a Vitest/ESLint/Vite toolchain and state the published package has no runtime dependencies — the profile of a frontend package. These lead to different ownership (Composer vs. resources/js), different failure modes (asset loading vs. render internals), and different migration plans. A TPM cannot sequence work on this until it is resolved. Fifteen minutes of triage — inspect composer.json, inspect src/, check for an auto-discovered service provider, render one hardcoded chart — settles it. Until then, no roadmap item should depend on this package.
Integration feasibility. Low-to-moderate, provided the Orchid precondition holds. The install path is a standard composer require plus a provider registration or publish step, and the first use case is deliberately small: one real metric on one real screen. The real cost is not installation, it is the conventions we layer on top — a base chart class, a semantic palette, a caching rule, a timezone boundary. Those are ours to write regardless of which library we use, and they are what makes the dependency cheap to replace later.
Technical risk.
braces advisory (GHSA-vfj7-8cjw-p6xm) rides in transitively via Stylelint. It is dev-only and the production audit is clean, but a blanket Dependabot suppression is how a real finding gets missed later. Scope the exception, set a review date.config('app.timezone'), blank canvases on empty datasets, and unbounded pluck() pulling entire tables into PHP on a page that loads on every admin view.Key questions to close before commitment.
config/app.php?src/, versus what the prose promises?Stack fit. Laravel + Orchid only. If we are not on Orchid, this assessment ends here; do not adopt it as a hedge for a future admin decision. If we are on Filament or Nova, the correct action is to write the wrapper ourselves against Chart.js, and the one-to-three-day estimate from the evaluation is the number to plan against.
Migration path. Spike first, integrate second. Run the identity triage in a throwaway branch, then build exactly one chart — "orders per day, last 30 days" — on the screen where a numeric list would otherwise live. That single artifact exercises the whole chain (query → chart class → layout registration → render) and gives us something concrete to debug against. If it renders, we standardize; if it fights us, we stop and take the build-ourselves path while the sunk cost is still measured in hours.
Two conventions carry the migration and should be established on that first chart, not retrofitted:
Compatibility. Pin "orchid/charts": "0.0.10" exactly — not ^0.0.10, not *. Verify the Orchid, Laravel, and PHP versions the package actually supports against ours before writing anything. If the frontend reading holds, also verify the Vite/Node toolchain compatibility and confirm whether Chart.js comes from the package or from our bundle. Resolve this at install time; a chart that renders axes but no data is usually the charting library loaded twice or not at all, and that diagnosis costs an afternoon if we discover it in a screen review instead of in a spike.
Sequencing.
What we are explicitly not doing. Not adopting it customer-facing, not adopting it as a hedge for an undecided admin stack, and not adopting it to avoid a day of wrapper work only to spend a week bending it to requirements it was never generic enough to meet.
Maintenance. Assign a named owner and a low investment ceiling from day one. This is an internal-tooling dependency, never something a customer-facing commitment rests on. Because the source is the documentation, require a comment block in each chart class recording the API shape as verified — it is the only onboarding material the team will have, and it is what makes the second developer productive without re-reading src/. Budget for pre-1.0 upgrade work as a recurring line item rather than a surprise; a dependency that shipped tooltip-callback fixes under an ESLint major will keep moving.
Support. There is no community to escalate to: zero stars, zero dependents, no third-party examples or answers. The failure mode this creates is not "we can't fix it," it is "one person knows how it works." Mitigate by having at least two engineers touch the integration during the spike and rollout, and by keeping the vendor coupling behind our own base class so the fallback is a known quantity.
Scaling. Two different cost profiles depending on which reading of the package is true, and both are manageable if we set the rules early:
pluck() an unbounded relation without limit(). Put the aggregation in a cache keyed by the query window — chart.orders.{from}.{to} — never by request()->fullUrl(), which explodes the key space. Invalidate on write, or accept a five-minute staleness on an analytics view.The genuine scaling risk is organizational, not technical: charts spreading from a handful of KPI panels to a de-facto analytics surface that this dependency cannot carry. Draw that line in the roadmap now.
Failure modes to plan for.
| Failure | Symptom | Mitigation |
|---|---|---|
| Identity misread | Assets don't load, or we hunt for a config option that doesn't exist | Triage before any code; assign ownership accordingly |
| Double-loaded charting library | Axes render, data doesn't | Confirm bundle source at install |
| Timezone bucketing | Chart count ≠ orders list count for "today" | One boundary, converted at the query layer, used by every chart class |
| Empty dataset | Blank canvas or broken scale instead of "no data" | Special-case empty payload in the chart class; show a placeholder on the screen |
| Tooltip callback regression after bump | Silent, user-visible behavior change | Pin exactly; visual check on upgrade, not just a render smoke test |
Unbounded pluck() |
Admin slows down over weeks | Aggregate in SQL; enforce in code review |
| Dev-advisory noise | CI fails repeatedly on a package we don't ship | Scoped audit exception with a review date |
Ramp-up. Low for any Laravel developer — the fluent API is not the friction. Half a day to productive on the existing chart classes, plus the verified-API notes as the entry point. The cost that does not compress is source-reading during the spike, which is why the spike is scheduled first and time-boxed rather than absorbed into a feature estimate.
How can I help you explore Laravel packages today?