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

Axis Laravel Package

epessine/axis

Axis is a modern, ultra-simple and flexible Laravel library for drawing charts entirely in PHP—no JavaScript boilerplate. It's built for Livewire and supports Chart.js, ApexCharts and Highcharts out of the box, with no configuration hell. Just install and draw.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Axis is a translation layer, not a renderer. It takes a fluent PHP builder (Chart::chartjs()->bar()->labels(...)->series(...)) and emits native configuration for Chart.js, ApexCharts, or Highcharts through a Blade render ({{ $chart }}). For a Laravel monolith this is the correct seam: it removes hand-maintained JS wiring from the critical path without adding a build step, a rendering engine, or a proprietary runtime. The genuinely differentiated piece is the #[Axis] Livewire attribute — charts survive Livewire re-renders with instance and state intact instead of being torn down and rebuilt. That specific problem is what teams currently hand-roll badly, and it is where the package earns its keep.

Abstraction ceiling. Two escape hatches bound the risk: raw native config arrays (Chart::chartjs([...])) and Script::from() for scriptable JS-function properties. In practice the abstraction is a convenience over a subset of each library's surface, not a complete model of it. The number that matters is escape-hatch rate: if more than roughly 25–30% of a roadmap's charts need raw config, you are paying an indirection tax to write JS config inside PHP strings and the value proposition inverts.

Integration feasibility. Low friction. composer require, optionally publish config, render in Blade or add the attribute in a Livewire component. The compatibility matrix is broad and current — Laravel 10–13, Livewire 3–4, PHP 8.2–8.5 — and v0.8.0 shipped ahead of ecosystem majors, which is a positive signal on maintenance intent but also means much of that matrix is untested by a real user base (0 dependents). A single Laravel developer can produce a working chart in under an hour; that is the whole pitch and it holds.

Technical risks, ranked.

  1. Bus factor and adoption signal. 27 stars, 0 dependents, single maintainer, pre-1.0. No security review, no CVE process, no SLA, no Stack Overflow corpus. This is an unhedged dependency on a revenue-critical surface.
  2. Pre-1.0 semver. Release history shows breaking changes in minor versions (v0.2.1 series param refactor, v0.6.0 IsFluent → AsAxisChart trait rename). Caret constraints are unsafe; pin exact versions.
  3. Livewire coupling. #[Axis] implies reliance on Livewire internals. A Livewire major is the most likely single-event breakage, and it lands on the framework upgrade path you cannot avoid.
  4. Asset/version skew. The PHP package generates config targeting a specific JS library version. How Chart.js/ApexCharts/Highcharts are delivered (CDN vs. published assets vs. Vite) and whether that version is pinned is the top unresolved failure mode — a silent mismatch yields a blank canvas with no server-side error.
  5. Script::from() injection surface. It writes JS functions into config. If any chart config is influenced by user or tenant input, that is an XSS vector. Hard rule required: never interpolate untrusted data into Script::from().
  6. Gaps you still own. Accessibility, data-table fallbacks, PNG/PDF/CSV export, custom tooltips, annotations, dark-mode fidelity, design-system conformance. None are evidenced as addressed.
  7. Image rendering (v0.6.0). Server-side PNG generation likely implies a headless-browser or Node runtime dependency — a material deployment and container-size change. Verify before it appears in a roadmap commitment.
  8. Highcharts licensing. Axis does not alter your commercial license obligation. Chart.js (MIT) is the only cost-free default.

Key questions to resolve before committing.

  • How are the JS libraries loaded, and can that version be pinned and audited?
  • What is the assertion surface in CI — can we test the generated config array, or only eyeball the browser?
  • Does image rendering require Node/Chromium in the deploy image?
  • Does the package surface any server-side signal when a chart fails to render client-side?
  • What fraction of our planned chart types are covered by the fluent API versus raw-config mode?
  • Is there a written fallback if upstream stalls: vendor, fork, or strip to raw config?

Integration Approach

Stack fit. Strong only under specific conditions: Laravel with server-rendered Blade and/or Livewire, a PHP-centric team, no existing design-system chart component, and charting surfaces that are internal or low-stakes. If the frontend is Inertia/React/Vue, or a house charting standard already exists, Axis creates a second divergent charting path and the trade turns negative. Confirm this filter first — it decides everything downstream.

Library choice stays separable. Adopt Axis and the Chart.js/ApexCharts/Highcharts decision in the same breath, but keep them decoupled in the plan. Default to Chart.js on license grounds; treat ApexCharts and Highcharts as opt-in per surface with explicit approval for Highcharts' commercial terms. This preserves the ability to drop Axis and keep the library, or swap libraries without touching the wrapper seam.

Dependency hygiene.

  • Pin an exact version ("epessine/axis": "0.8.0", not ^0.8). Given minor-version breaking changes, non-negotiable.
  • Pin the underlying JS library version alongside it and record the pairing in the repo.
  • Constrain PHP and Laravel versions in composer.json and verify the package's claimed matrix in your own CI job rather than trusting the README.
  • Add a Renovate/Dependabot rule that routes Axis bumps to a human, never auto-merge.

Isolation seam. Wrap all chart construction behind one internal helper or facade (App\Support\Charts\ChartFactory) plus a single Blade component. Every chart goes through it. That makes the dependency a one-file swap if you fork or replace it, gives you one place to enforce the "no untrusted data in Script::from()" rule, and gives you one place for cross-cutting concerns (empty states, telemetry, default palette). Keep every chart's configuration expressible as a plain array so exit is copy-paste.

Migration path. No migration — greenfield adoption. The realistic path is to prove on one net-new surface and only retrofit existing charts where a surface is already being rewritten. Do not schedule a "convert our charts to Axis" epic; the ROI is in new work, and retrofits are where you discover the abstraction gaps.

Sequencing.

  1. Spike (1–2 days, one dev). One internal dashboard, three chart types, Chart.js only, pinned version, through the factory seam. Deliberately exercise the escape hatch once to see what raw-config mode actually costs.
  2. Internal pilot (one sprint). Ship 3–5 charts on an admin/ops surface. Instrument rendering failures. Measure actual hours against the JS hand-off estimate.
  3. Gate review. Go/no-go against written criteria: escape-hatch usage rate, defects attributable to Axis, time saved, and whether the asset/version story is clean.
  4. Contained customer surface (one MVP reporting feature). Only if the gate passes. Design-system, accessibility, and export requirements remain yours — budget them here, not later.
  5. Standardize or exit. Either promote Axis to the sanctioned charting path or strip to raw config. Do not let it drift into "the thing two dashboards use" indefinitely.

Operational Impact

Maintenance. Ongoing cost is low in volume and high in concentration. The API surface is small and upgrades are infrequent (roughly one minor per framework major), but you are your own vendor: when a Livewire upgrade breaks #[Axis], there is no one to escalate to. Budget a named owner and a standing half-day per framework major upgrade cycle to validate chart rendering, plus a documented fork/vendor procedure. Weighed against the alternative — 1–3 developer-days per charting surface plus permanent JS maintenance — the arithmetic usually favors Axis for a PHP-heavy team, provided the fork plan exists.

Support. Self-support only. No vendor, no SLA, no security-response commitment. Mitigations: read the source (it is small), subscribe to repo releases and issues, and keep the wrapper seam thin enough that debugging never requires understanding the whole package. Docs exist and are reasonable for a beta, but expect gaps and treat the source as the spec.

Scaling. Rendering is client-side, so scale concerns are payload and round-trip, not compute. Watch three vectors: charts per page (each is an independent library instance with its own canvas and JS cost), dataset size serialized into the Blade payload (large series bloat HTML and the Livewire re-render diff), and Livewire round-trip frequency on filterable dashboards (a date-range picker re-emitting five charts can dominate perceived latency). Mitigations are conventional — server-side aggregation and downsampling, lazy-load below-the-fold charts, debounce filters, paginate drill-downs — but they are decisions someone must make, and Axis does not make them for you.

Failure modes. The dangerous ones are silent: version skew between the PHP package and the loaded JS library, a Script::from() payload that parses server-side but throws client-side, or a Livewire re-render that orphans a chart instance. All three present as a blank div with a clean server log. Countermeasures: a Playwright smoke test asserting canvas presence on your top charts, client-side error reporting wired into your existing frontend telemetry, and a consistent empty-state in the shared Blade component so a failed chart never masquerades as "no data."

Ramp-up. Near zero for anyone who writes Laravel. The mental model is one fluent builder plus one Blade include, and a mid-level developer is productive in a day. The skill that actually needs training is judgment: knowing when to drop to raw config, and knowing never to feed user input into Script::from(). Encode both in the factory seam and a short internal README rather than in tribal knowledge.

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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel