friendsofvictoire/tab-widget
A Laravel package that provides a reusable tabbed widget for grouping content into switchable panels. Define tabs and their contents in PHP, then render a clean tabbed interface in dashboards or admin pages to keep dense information organized and easy to navigate.
Architecture fit — poor, and likely a category error. The package is published as friendsofvictoire/tab-widget but the underlying repository is FriendsOfVictoire/WidgetTabBundle. The *Bundle suffix and the "FriendsOf" naming convention (a Symfony community pattern) indicate this is a Symfony bundle, not a Laravel package. Symfony bundles integrate through AppKernel/bundles.php registration, the Symfony DI container, and typically Twig — none of which Laravel's service-provider container, facades, or Blade layer understand. There is no laravel/ bridge, no Illuminate\Support\ServiceProvider subclass implied by the name, and no extra.laravel block in evidence. In a Laravel context this is not a package you install so much as a parallel framework runtime you would drag in.
Intrinsic value is small. The name suggests a UI concern: rendering tabbed widget panels, most likely for an admin/dashboard surface (the FriendsOfVictoire ecosystem is Sonata-adjacent). That is presentation-layer glue. Even in the best case — the tab/widget logic being framework-agnostic PHP with a thin Symfony wrapper — the reusable core is plausibly a few hundred lines of array-shaping and render logic. A TPM should treat the build-vs-adopt comparison as roughly "a few days of Blade/Livewire work" versus "an indefinite fork ownership liability."
Integration feasibility — technically possible, practically negative. Composer will PSR-4 autoload the classes, so a hand-rolled extraction is not impossible. But if the bundle declares dependencies on symfony/http-kernel, symfony/dependency-injection, symfony/config, twig/twig, or sonata-project/*, you end up with two container abstractions and two templating engines inside one process. The last release is 2016-08-22, which places the constraint set in the PHP 5.5–7.0 / Symfony 2.7–3.0 era. Current Laravel (10/11) requires PHP 8.1+. Composer resolution will very likely fail outright, and --ignore-platform-reqs simply defers the failure to runtime.
Technical risk — severe, compounding. Adoption signals are effectively zero: 2 stars, 0 dependents, no release in ~9 years. Zero dependents is the most diagnostic number here — it means no one has exercised this against a real dependency graph, so there is no field evidence of it working even in its native Symfony habitat. There is no security response path: no maintainer activity means a CVE would ship unpatched, and Laravel's composer audit/CI security gates would flag abandoned packages.
Key questions to resolve before any further investment:
opportunity: 0.76 score actually measuring? Opportunity heuristics reward low-adoption/high-gap packages; a TPM should not let a gap-detection score override abandonment and ecosystem-mismatch evidence.Recommendation: reject for adoption; evaluate as design reference only. The composite score (1.11) and adoption profile are consistent with "do not integrate."
Stack fit — no direct fit. Target stack is Laravel on PHP 8.1+ with Composer 2, Blade or Livewire for views, and Laravel's service container. The package targets Symfony 2/3 on PHP 5.x/7.0 with Twig. These are not adjacent versions of the same thing; they are different integration contracts.
Migration path, if a spike is authorized anyway: treat it as a source extraction, not an install.
| Step | Action | Exit criterion |
|---|---|---|
| 1. Discovery spike (1–2 days) | Clone repo, read composer.json and the bundle class; identify which classes touch Symfony/Twig |
Written inventory: framework-agnostic core vs. Symfony-coupled wiring |
| 2. Dependency probe | Attempt composer require in a throwaway Laravel app on the target PHP version |
Clean resolve, or documented hard blocker |
| 3. Decision gate | Compare extracted core LOC against a Blade/Livewire reimplementation estimate | Go/no-go with a cost delta, not a preference |
| 4. Fork (only if step 3 favors it) | Vendor the agnostic classes under app/Support/, add a WidgetTabServiceProvider, expose a Blade component |
Green CI on PHP 8.1–8.3, test coverage on extracted logic |
| 5. Never vendor the bundle | Do not register Symfony bundles or boot a Symfony kernel inside Laravel | No symfony/http-kernel in composer.lock |
Compatibility posture. Assume incompatibility until proven otherwise. Any adoption must be gated on: PHP 8.x compatibility verified in CI, no symfony/http-kernel or twig/twig in the resolved graph, and a pinned fork under our own namespace. Under no circumstances should --ignore-platform-reqs be the mechanism that makes install succeed — that is a signal to stop, not to proceed.
Sequencing relative to product work. This must not sit on a critical path. Run the spike in parallel with whatever the actual dashboard requirement is, and pre-commit to reimplementing if the spike does not return a clean result inside two days. The expected outcome is reimplementation; the spike exists to make that decision defensible rather than assumed.
Preferred alternative. Build the tabbed-widget surface directly as a Blade component or Livewire component (or adopt an actively maintained admin-panel package already in consideration). This keeps the code inside our PHP version support window, inside our security patching process, and inside our own test coverage.
Maintenance — the dominant cost. Upstream is dormant: no release since August 2016, 2 stars, no visible maintainer throughput. Adopting it means forking it and owning it permanently. Every future PHP major (8.4, 9.x) becomes our migration, not the maintainer's. Every Laravel major becomes our compatibility patch. This is a recurring, unbounded cost against a one-time reimplementation saving — the economics invert within the first upgrade cycle.
Support — effectively nonexistent. No maintainer to escalate to, no issue-tracker throughput to rely on, negligible community footprint (2 stars implies no meaningful StackOverflow or discussion corpus). Internal engineers will be the only source of truth, and that knowledge will be concentrated in whoever runs the spike — a bus factor of one.
Scaling — negligible runtime cost, non-trivial process cost. As a presentation-layer concern, rendering overhead is immaterial at any realistic request volume. The real scaling risk is architectural: if any part of the integration bootstraps Symfony kernel or container services inside a Laravel request, you pay double-bootstrap memory and latency on every request that touches it, and you inherit two configuration/caching layers to reason about during incidents.
Failure modes, ranked by likelihood:
Ramp-up. Low technical learning curve (the surface is small), high archaeological cost (2016 Symfony idioms, likely thin or absent docs, no examples in the wild). Realistically budget the two-day spike plus a half-day writeup; do not budget a multi-sprint integration. If the spike exceeds that box, that itself is the finding.
Bottom line for the roadmap: this package does not represent a build-vs-buy decision — it represents a build-vs-fork-an-abandoned-Symfony-bundle decision, where the fork is guaranteed and the upstream is not a party to it. Recommend closing it out with a documented rejection and a reimplementation ticket sized against the actual dashboard requirement.
How can I help you explore Laravel packages today?