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

Visjs Bundle Laravel Package

stinger/visjs-bundle

stinger/visjs-bundle integrates the vis.js visualization library into PHP applications, bundling its assets and providing helpers to render interactive networks, timelines, and graphs. It handles asset loading and configuration so developers can embed dynamic, data-driven visualizations without writ...

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is a Symfony2 bundle from 2015 with zero stars and zero dependents — it is not a Laravel package and has no service provider, facade, or config file Laravel can read. Read the repo in this order before installing anything:

  1. composer.json — check the symfony/* and twig/twig constraints. They will almost certainly conflict with any Laravel 9+/10+/11 app (symfony/symfony ~2.x and modern symfony/* components cannot coexist). Expect composer require to fail; that failure is the answer, not a puzzle to solve.
  2. Resources/views/ — this is the only part with transferable value. It shows the container <div> + inline <script> pattern the bundle generates.
  3. The Twig extension (Twig/ or DependencyInjection/) — it is a thin wrapper that serializes a PHP array of options to JSON and emits a new vis.Network(...) call. That logic is ~30 lines and easy to port.
  4. Resources/public/ or bower.json — identifies which vis.js version the bundle targets (likely 3.x/4.x, pre-vis-network split).

Minimal path for a Laravel app: don't install the bundle. Take the concept and use the modern successor package:

npm install vis-network vis-data
// resources/js/app.js
import { Network } from 'vis-network';
import { DataSet } from 'vis-data';
window.vis = { Network, DataSet };

Then convert the bundle's Twig template into a Blade component. First use case: a "network graph of related entities" admin page (users↔roles, tags↔posts) rendered as nodes/edges from an Eloquent query.

Implementation Patterns

Blade component instead of Twig extension. Port the bundle's serializer into a component that owns the container + init script:

{{-- resources/views/components/vis-network.blade.php --}}
@props(['nodes' => [], 'edges' => [], 'options' => [], 'height' => '500px'])
<div id="{{ $id = 'vis-'.Str::random(8) }}" style="height:{{ $height }}"></div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', () => {
  const nodes = new vis.DataSet(@json($nodes));
  const edges = new vis.DataSet(@json($edges));
  new vis.Network(document.getElementById(@json($id)), {nodes, edges}, @json($options));
});
</script>
@endpush

Server-side graph builder. If you liked the bundle's array-based API, write a small VisGraph class that returns ['nodes' => [...], 'edges' => [...], 'options' => [...]] from your models. This keeps controllers clean and makes the graph testable (assert on the array, not the canvas):

final class VisGraph
{
    public function nodes(iterable $models, string $labelKey = 'name'): array { /* ... */ }
    public function edge(int|string $from, int|string $to, array $extra = []): array { /* ... */ }
    public function toArray(): array { /* ... */ }
}

Progressive loading for larger graphs. The 2015-era pattern of dumping every node in the initial payload does not scale. Return the initial subgraph from the controller and fetch expansions from a JSON endpoint, mutating the DataSet in place:

Route::get('/graph/{entity}/neighbors', fn (Entity $e) => response()->json([
    'nodes' => ..., 'edges' => ...,
]));
const res = await fetch(url).then(r => r.json());
nodes.update(res.nodes); // merge, don't recreate the Network
edges.update(res.edges);

Options as a PHP preset. Ship named presets ('hierarchy', 'physics-off', 'timeline') in a config file and merge them, rather than repeating 40-line option arrays per page. This mirrors what the bundle's visjs: config keys were meant to do, but under config/vis.php where Laravel can cache it.

Alpine/Livewire integration. Wrap init in an Alpine x-init and always call network.destroy() on teardown — Livewire morphs will otherwise leak a canvas and a physics simulation per navigation.

Gotchas and Tips

  • The version gap is the main trap. The bundle predates the vis monolith being split. vis-network@9 has no global vis object, DataSet lives in vis-data, and options like physics.stabilization behave differently. Any code copied from the bundle's templates will silently no-op or throw. Pin to vis-network + vis-data and rewrite, don't translate.
  • No asset publishing in Laravel. The bundle's Resources/public + Assetic workflow does not exist here; there is no php artisan vendor:publish for it. Use Vite and let npm manage the library. Never hand-copy vendored JS into public/.
  • The container needs an explicit height. vis-network renders into a zero-height div as a blank page — the most common "it's broken" report. Set height on the wrapper, not the canvas.
  • Twig is not Blade. {{ vis_network(...) }} must become a component or directive; |raw means nothing; @json already escapes for HTML-context script tags, so don't double-encode with json_encode inside Blade.
  • Physics is a performance cliff. Above ~300 nodes, disable physics after stabilization (network.once('stabilizationIterationsDone', () => network.setOptions({physics:false}))) or the tab pegs a CPU core.
  • Canvas is untestable server-side. Assert on the JSON payload in Pest/PHPUnit; if you need render coverage, drive it with Playwright/Dusk and check network.body.data.nodes.length, not pixels.
  • CSP: inline <script> with @push('scripts') will break under a strict script-src. Either allow a nonce on the pushed script or move init into a Vite module that reads a JSON blob from data-* attributes.
  • Extension point worth keeping: the bundle's one genuinely reusable idea is "PHP array in, JS config out." Keep that boundary — it is what lets you swap vis-network for Cytoscape.js or D3 later without touching controllers.
  • Licensing is fine but provenance isn't. The bundle is MIT and vis.js is MIT/Apache-2.0, so copying snippets is legal; the risk is copying 2015 API calls into a 2024 dependency tree. Treat the repo as documentation of an idea, not as a dependency.
  • If you are genuinely stuck maintaining a Symfony2 app that already uses it: the bundle's Twig function name is your debugging anchor — grep -r "vis" vendor/stinger/ for the extension class, and check app/config/config.yml for the visjs: keys, since option merge behavior lives there, not in the bundle defaults.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle