leandrocfe/filament-apex-charts
ApexCharts integration for Filament with an artisan widget generator and support for area, bar, line, pie, donut, radar, heatmap, treemap, funnel, and more chart types for dashboard panels.
Architecture fit. This is a thin presentation-layer adapter, not a platform dependency. It contributes three things to a Filament panel: a plugin registration (FilamentApexChartsPlugin), a widget base class (ApexChartWidget) that extends Filament's widget lifecycle, and an artisan generator that scaffolds ~19 chart types plus an "empty" stub. Data access, persistence, and authorization remain entirely ours. Fit is therefore binary: high if we already ship Filament panels, zero if we do not — the gating question is panel adoption, not charting.
The real value is not "ApexCharts in PHP" (we could hand-write that in a Blade view); it is the ergonomics layered on top: filter schemas via HasFiltersSchema, deferred loading with readyToLoad, dark-mode handling, collapsible headers, footer slots, and a documented polling model. Those are the pieces we would otherwise rebuild per widget.
Integration feasibility. Low friction. Composer install, one ->plugins([...]) line in the Panel provider, one artisan command. First chart on screen in under a day. The only non-obvious constraint is the version matrix: package majors are pinned to Filament majors (2.0.2 → Filament v2, 3.2.1 → v3, 4.0.0 → v4, ^5.0 → presumably the newest). This must be treated as a hard constraint, and it must be verified from composer.json, not from README prose — the README's usage examples cite Filament 5.x schema docs while the install snippet targets ^5.0, which is an alignment ambiguity worth resolving in the spike.
Technical risk.
SECURITY.md or CVE process. MIT license is the mitigation: we can vendor a fork permanently if needed.extraJsOptions() returns RawJs string content injected client-side. If any of that is ever interpolated from user- or tenant-controlled data, it is an XSS vector inside an authenticated admin surface. Treat this as a policy item, not just a code-review item.Key questions to answer before committing.
^5.0 actually support it? Validate against the package's composer constraints and a real install.composer test script?RawJs?Stack fit. Laravel + Filament panel, PHP 8.x, Livewire runtime, client-side JS rendering. Strong fit for internal/back-office dashboards and reporting screens. Poor fit for public-facing, SEO-critical, or very high-concurrency reporting — the output is a Livewire component with a large client-side JS library, not a server-rendered artifact.
Migration path. Do not big-bang. If we already use Filament's native ChartWidget (Chart.js), keep it and adopt Apex only for chart types Chart.js renders poorly: heatmap, treemap, candlestick, boxplot, funnel, timeline range bars, radial bar, polar area, bubble, range area. If we have bespoke Blade + ApexCharts already, this package is a consolidation target — porting those into ApexChartWidget subclasses buys filter schemas, defer loading, and dark mode for free.
Exit cost is bounded and worth stating up front: removing the dependency means rewriting widget classes to native ChartWidget or a custom Blade partial. That is a per-widget mechanical job, not an architectural one — acceptable reversibility.
Compatibility. The version matrix is the compatibility artifact. Encode it explicitly as package-major ↔ Filament-major ↔ minimum Laravel/PHP, pin exactly in composer.json, and let automated dependency tooling propose bumps. Treat a Filament major upgrade as a scheduled project with a test pass over every chart widget, not a patch release.
Sequencing.
$pollingInterval, $deferLoading threshold, static-only RawJs rule, empty-state behavior.Maintenance. Two surfaces to own: the dependency itself, and our widget classes plus anything published. Budget a recurring slice each Filament major cycle. Because MIT lets us patch in place inside vendor/ and mirror the repo internally, the concrete contingency for abandonment or an unfixed security issue is a fork — decide the trigger now (e.g., no release within 90 days of a Filament major, or an unaddressed security report) rather than during an incident.
Support. Channel is GitHub issues plus a personal email. No SLA exists, so do not promise one internally. For an admin-only tool that is tolerable; escalate to the fork path if median issue response degrades or a critical Filament incompatibility lingers.
Scaling. The scaling risk is the polling model, not the package. Load grows as open dashboard tabs × widgets per tab ÷ interval. Controls: set $pollingInterval explicitly per widget or disable it, use $deferLoading for slow work, move aggregation into summary tables or cache, and forbid unbounded getOptions() queries on shared dashboards. Client-side, ApexCharts renders in the browser — series with thousands of points will jank; downsample server-side. Many widgets per page also inflate Livewire payloads, so watch component count per dashboard as much as query cost.
Failure modes.
RawJs fed from dynamic data → XSS in an authenticated surface. Mitigate with a static-literal-only rule plus review gate.getOptions() → dashboard timeout, recurring because of polling. Mitigate with defer loading and query budgets.Ramp-up. A mid-level Laravel developer is productive within hours, because the API surface is literally "return an array matching the ApexCharts options object." That is also the catch: the package abstracts almost nothing. Every developer still needs ApexCharts option fluency, and the recurring effort is design-to-chart translation (formatters, axes, tooltips, color tokens), not package learning. Plan roughly half a day of onboarding using the linked demo repo, then invest in a short internal cookbook covering polling policy, RawJs policy, defer-loading thresholds, empty states, and chart-id naming — otherwise conventions drift across widgets within a quarter. Staff one owner, front-end-leaning, to hold the cookbook and the fork.
How can I help you explore Laravel packages today?