schmeits/pulse-panphp
A Laravel Pulse card that integrates PanPHP's privacy-friendly analytics into your Pulse dashboard, letting you monitor page views, visitors, and traffic trends alongside application health metrics. Simple to install and configure.
The package is at 0.0.1 — a first release with no changelog history to diff against. Treat everything below as a starting checklist to verify against the actual source rather than settled behaviour.
Start by confirming what you actually installed:
composer require <vendor>/<package>:0.0.1
composer show <vendor>/<package> # version, deps, autoload, suggested packages
Check the installed tree for the three things that tell you most about a Laravel package's shape:
composer.json → extra.laravel — whether the service provider and any facades are auto-discovered. If they're not registered there, you're manually adding them to bootstrap/providers.php (Laravel 11+) or config/app.php (10 and below).src/ root — look for a *ServiceProvider.php with register() and boot(). register() is what binds singletons and merges config; boot() is what publishes assets, registers commands, routes, migrations, and Blade components. Reading only the provider gives you roughly 80% of the surface area in a few minutes.config/ — if a config file ships, publish it immediately (php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider") and commit it. Unpublished config is the single most common source of "works locally, wrong in staging".The natural first use case is the package's own README example, run verbatim in a throwaway branch on a scratch model/table. If the README is thin (expected at 0.0.1), write the smallest possible call yourself — one method invocation, assert the output with dd() or a Pest test — before wiring it into real application code.
Bind-and-inject over facades. Prefer constructor injection of the package's contracts/classes in your own services and jobs. Facades are convenient in controllers and tinker, but they hide the dependency and make tests that don't boot the full app harder. If a facade exists, check whether the underlying class is bound as a singleton — if so, injecting it into two services means shared mutable state.
Wrap, don't scatter. Put a thin adapter class around the package in app/Support/ or a dedicated domain namespace. Every upgrade then touches one file instead of forty call sites. This matters disproportionately at 0.0.x, where method signatures can change in a patch release.
Queue and console as the primary integration points. Most Laravel packages of this shape do their real work in a job or an artisan command. Register the command from your own AppServiceProvider rather than relying on the package's boot() if you need to control scheduling, or wrap the job in your own job so you own retries, backoff, $timeout, and failed() handling rather than inheriting whatever the package chose.
Feature-flag the first rollout. Put the call behind a config value or Pennant flag that defaults to off in production. On a 0.0.1 you want to be able to disable it without a deploy.
Test against the real thing, not a mock, at least once. Write one feature test that boots the provider and exercises the real code path against SQLite or a container service. Then mock the adapter for everything else. Mocking a package you've never seen run successfully is how you end up with 100% coverage and a broken feature.
Pin the version and let Renovate/Dependabot open PRs. composer require "<vendor>/<package>:0.0.1" as an exact constraint is correct here — see the caret caveat below. Review each bump by reading the diff in vendor/ until a 1.0.0 lands.
The caret operator traps you. Composer treats ^0.0.1 as >=0.0.1 <0.0.2, not <1.0.0. Any 0.0.2 release is a breaking-change-allowed bump that Composer will refuse to install under a caret. Pin exactly and upgrade deliberately; don't assume ^0.1 semantics apply.
No composer.lock diff, no safety net. Because this is the first release there's no prior tag to read, so composer update gives you no changelog to consult. Keep a short docs/decisions/ note on why you adopted it and which methods you depend on. When 0.0.2 appears, that note is your grep list.
Config merge vs. publish is not the same thing. mergeConfigFrom() in register() gives you defaults; publishes() in boot() gives you an editable file. If you publish and also rely on defaults being merged, a stale published file will silently shadow new keys added in later versions. Re-publish with --force after upgrades and diff.
env() outside config files returns null under config:cache. If the package calls env() directly in boot() or in a service class, it will work in php artisan serve and break the moment you deploy with cached config. Grep the package for env( and, if found, set the value through your own config/ file and override the package config key instead.
Singletons retain state across requests in Octane. If the package binds a singleton that memoises results, it will leak between requests under Laravel Octane or in long-running queue workers. Check for a flush/reset method or add one to your Octane warm/flush listeners.
vendor:publish tags are worth knowing. Run php artisan vendor:publish with no arguments and look for the package's tag group. Tags are more stable than provider FQCNs, which occasionally move between namespaces in early releases.
Debugging order that actually works: (1) php artisan about to confirm the provider booted; (2) php artisan tinker and resolve the class from the container to confirm the binding; (3) set APP_DEBUG=true and check whether exceptions originate in the package or your adapter — if it's the package, that's an upstream issue, not your bug; (4) composer why <vendor>/<package> to see if something else dragged it in transitively.
Extension points to prefer, in order of safety: config values → your own wrapper class → package events/listeners (if any ship) → decorating a bound interface in your provider (rebind after the package's register() runs) → forking. Class extension is last resort at 0.0.x because internals aren't stable; if you must, mark your subclass with a comment pointing at the exact upstream version it target
Expect missing pieces. No LICENSE audit, possibly no README examples, no documented support matrix for PHP/Laravel versions. Check composer.json require for the Laravel constraint and confirm it covers your version before building on it, and confirm the license permits your use — both are cheap to check and expensive to discover late.
How can I help you explore Laravel packages today?