beyondcode/polyscope
Polyscope by Beyond Code adds a polished, Livewire-powered dashboard to your Laravel app, letting you browse routes, inspect logs, and monitor runtime details without leaving your admin panel. Simple to install, easy to customize, and handy for debugging in development or staging.
Architecture fit — unresolved, and that is the finding. The package presents four mutually incompatible identities across the supplied material: its composer description calls it a "Laravel SDK for the Polyscope API," its own feature list describes combining multiple Livewire components on one page, one technical assessment evaluates it as a polymorphic query-scope helper, and another treats it as an observability/telemetry or multi-tenancy layer. These are four unrelated products with unrelated value propositions, integration costs, and risk profiles. With 0 stars and 0 dependents, there is no community signal to adjudicate between them. A TPM cannot make an architecture-fit judgment on a package whose category is undetermined; the only defensible position today is that fit is unverified.
Integration feasibility — a two-hour spike, not a sprint. Feasibility hinges entirely on which product it turns out to be:
description.md reading): feasibility is high and scoped — it fills the real gap between Livewire's one-root-component-per-page constraint and a composable layout. The integration surface is Blade templates and a layout, and the risk is contained to the view layer.whereHasMorph generation covers roughly 80% of the described value in ~40 lines the team fully controls.stancl/tenancy (multi-site) are strong first-party or well-adopted alternatives.In every branch, the first deliverable is a spike reading vendor/beyondcode/polyscope/{composer.json, src/} to confirm the require block and the service provider's register()/boot().
Technical risk — dominated by identity risk, then lifecycle risk. Three risks stack:
Key questions for the diligence review:
PolyscopeServiceProvider::register()/boot() actually do — register a trait/builder macro (query scopes), a singleton client (telemetry), middleware (tenancy), or a Blade/Livewire component (composition)?require block depend on illuminate/database only, on guzzlehttp/guzzle, or on livewire/livewire?Stack fit — verify before committing, then sequence by layer. The stack-fit decision cannot precede the identity decision. Once the source read confirms the product, fit should be assessed against the layer it touches:
where clauses into one shared scope) has real, recurring value. If we have one or zero polymorphic relations, the package is solving a problem we do not have.Migration path — first use case, then convention, then breadth. Adopt in three stages, any of which can abort:
Compatibility — pin, wrap, and prove against our versions. Pin the exact version (not ^) in composer.json and record the tested Laravel/PHP combination. Check whether the service provider is auto-discovered; with zero dependents, assume nothing is wired for us. If the query-scope reading holds, pair adoption with Relation::enforceMorphMap() and verify the package resolves types via getMorphClass() rather than ::class — class-name-vs-alias resolution is the most likely production-only failure. If the Livewire reading holds, compatibility testing is against our Livewire version and page-routing model, and the upgrade risk shifts to Livewire's release trains.
Sequencing — spike, decide, then adopt or skip. The sequencing is: (1) half-day source read and identity confirmation; (2) build-vs-buy comparison against the internal alternative (the ~40-line trait, or the internal Livewire-composition helper) for the confirmed identity; (3) single-use-case spike with equivalence tests; (4) wrap-behind-our-own-class and pin; (5) convention rollout. If the spike reveals a thin wrapper around whereHasMorph (or around stock Livewire directives), the correct decision is to skip the dependency and keep the internal wrapper — the package earns its place only if it demonstrably solves constrained eager loading across heterogeneous morph types, or the Livewire composition case, more cleanly than our own code.
Maintenance — assume ownership, budget for it. With 0 stars and 0 dependents and a single maintainer, treat any adoption as a de facto fork: we will own compatibility fixes across Laravel majors. Contained in the model layer, this can mean touching every polymorphic query when the package stalls; contained in the view layer, it can block Livewire upgrades. Mitigation is structural: wrap the package behind a single internal class (CommentableQuery, MorphQuery, or a composition helper), keep vendor imports out of controllers and models, and pin the version. When the package stalls, replacement should touch one file. This is a standing line item in the engineering plan, not a footnote.
Support — vendor support is minimal; internal expertise is the support model. The only support guarantee is our own team's understanding of the source. Documentation (a README plus feature bullets) is not sufficient to debug runtime failures, and community answers will not exist. The mitigation is that the wrapped, single-file exit path keeps the support obligation bounded — a new engineer can replace one class rather than reverse-engineer a dependency.
Scaling — measure the query shape before scaling claims. For the query-scope reading, performance behaviour is the material scaling question: whether the package emits one query per morph type versus a single union, and whether eager loading stays eager or silently degrades to lazy loading (which makes performance worse for readability). Measure with DB::listen() before and after on representative data volume. Add the composite (morph_type, morph_id) and scope-filter indexes ourselves — the package will not ship migrations. Mixed-morph pagination is a schema problem (denormalised feed table) the package will not solve. For the Livewire reading, scaling concerns are request count per page and whether isolated component state degrades under many nested components on one route.
Failure modes — enumerate and instrument for each.
BadMethodCallException at query time, often only on the code path that touches that type — this is a fatal, not a noisy, failure. Mitigate with a five-line CI test iterating every registered morph alias and asserting each responds to each shared scope name.post compared against App\Models\Post silently break every scope, and stage data with legacy FQCN rows will mask it.Model::count(), factory creation, queue serialisation, and RefreshDatabase seeding. Confirm whether it registers globals and whether an withoutGlobalScope escape hatch exists; local scopes are the safer default.Ramp-up — low cost for the team, real cost for the owner. If the package is a thin wrapper (the most plausible reading in the query-scope and Livewire branches), an engineer familiar with the underlying primitive (whereHasMorph, @livewire) ramps in under a day. The real ramp-up cost is the maintainer — whoever owns the wrapper, the pin, the CI scope-guard test, and the upgrade-rehearsal that proves the package survives the next Laravel/Livewire major. Budget that as a fraction of one engineer's time per upgrade cycle. The honest baseline remains that a shared trait plus generated whereHasMorph closures, or an internal Livewire composition helper, delivers the described value in a few dozen lines the team fully controls — so the ramp-up cost is only justified if the spike proves the package is clearly better and safe to depend on. The decision this package supports today is "spike or skip," not a roadmap commitment.
How can I help you explore Laravel packages today?