muspelheim/c3charts-bundle
A Symfony bundle for building interactive C3.js charts. It provides services and Twig helpers to render responsive, data-driven visualizations with minimal configuration, keeping chart setup clean and reusable across your application.
First, the reality check: this is a Symfony bundle, not a Laravel package. It has no service provider, no Blade directives, and no config/c3charts.php to publish. Its only release is from 2018-11-20, it has 4 stars and 0 dependents, and the underlying C3.js library is itself in maintenance mode. For a Laravel developer, "getting started" is really a decision point:
composer require muspelheim/c3charts-bundle, register it in config/bundles.php (or AppKernel on older Symfony), and start with the bundle's Twig extension to render a chart from a controller.Where to look first:
src/ directory: chart-building classes (the PHP that assembles C3's data, axis, bindto, tooltip config) and the Twig extension that exposes the render function.Resources/views (or equivalent) for the template that outputs the <div id="..."> and the c3.generate({...}) call.composer.json — check the Symfony version constraints before assuming it runs on anything modern.Minimal first use case (Symfony context): load d3 and c3 (CDN or asset pipeline), render the bundle's chart tag into a container <div>, and pass a simple ['data' => ['columns' => [['data1', 30, 200, 100]]]]-shaped array. The bundle's value is converting PHP arrays into the exact JSON C3 expects plus the init script.
Minimal first use case (Laravel context): skip the bundle entirely. Add c3 + d3 via npm/Vite, then produce the options array server-side in a small ChartFactory class and hand it to a Blade component that calls c3.generate(). You keep 90% of the bundle's benefit with none of the framework mismatch.
Controller-builds-chart pattern (the bundle's intended shape). Construct a chart object in the controller, set series/axes/type, pass it to the view, and let the Twig extension emit the markup + JS. Mirror this in Laravel with a dedicated class rather than fattening controllers:
// app/Support/Charts/ChartConfig.php (ported idea)
final class ChartConfig
{
public static function line(array $series): array
{
return [
'bindto' => '#revenue-chart',
'data' => ['columns' => $series, 'type' => 'line'],
'axis' => ['y' => ['label' => 'Revenue']],
];
}
}
Blade component wrapper. Wrap the output so your views stay clean and the C3 dependency is isolated:
{{-- resources/views/components/c3-chart.blade.php --}}
<div id="{{ $id }}" wire:ignore></div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', () => {
c3.generate({!! Illuminate\Support\Js::from($config) !!});
});
</script>
@endpush
Livewire / Inertia integration. Charts are client-side; if data changes reactively, keep the config in a public property and re-run c3.generate() (or chart.load()) in a $watch/updated hook. The bundle has nothing to offer here — this is where a port beats the package.
API-driven series. The strongest day-to-day pattern is: JSON endpoint (Route::get('/api/charts/revenue')) returns series arrays; the Blade shell is static; the JS fetches and renders. This avoids re-rendering server templates and sidesteps the fact that the bundle's server-side rendering is static snapshot only.
Multi-chart dashboards. Give each chart a unique bindto id; the bundle historically assumes a single chart per render call, so a dashboard is just N component inclusions. In Laravel this maps cleanly onto a <x-c3-chart> component in a loop.
ServiceProvider, no facades. composer require will install Symfony bundles and Twig as transitive deps, bloating a Laravel app. Treat it as a reference implementation, not a dependency.composer.json require before anything else.d3 not loaded before c3, or the bindto selector not present at DOMContentLoaded. Check the console for c3 is not defined and verify the container <div> id matches exactly (including #).<script> tag, ensure it is JSON-encoded safely (Laravel's Js::from() / @json). The 2018 code likely predates strict CSP/escaping habits.ChartFactory — keep it small, typed, and returning pure arrays so it stays testable (assertSame on the options array is a great unit test).How can I help you explore Laravel packages today?