pschocke/nova-plausible-analytics
Bring Plausible Analytics into Laravel Nova with a dashboard card that shows visitors, pageviews, bounce rate, and top traffic sources without leaving your admin panel. Lightweight, privacy-friendly stats at a glance.
Minimal steps
composer require vendor/package:^1.0
composer.json inside vendor/vendor/package/ and check two things: the require block (PHP and illuminate/* versions) and the extra.laravel block. If providers/aliases are listed there, the package is auto-discovered and you need to do nothing. If they are absent, register the service provider manually — bootstrap/providers.php on Laravel 11+, config/app.php on 10 and below.php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"
Use --tag= to be selective; blind-publishing dumps config, migrations, views, and assets you may never touch.php artisan about and php artisan config:show vendor-package to confirm the package registered and your config file is actually being read.Where to look first
vendor/vendor/package/tests/ — in a mature package this is more accurate documentation than the README, especially for edge cases the README glosses over.src/*ServiceProvider.php — this is the package's real entry point. Everything it binds, tags, publishes, and registers is the actual surface area you're integrating with.CHANGELOG.md / upgrade notes for the version you're on.First use case
Pick the single thinnest end-to-end path and prove it in php artisan tinker or a throwaway route before wiring it into domain code. Resolve the package's main class from the container and call one method. If that works, you've validated autoloading, provider registration, config resolution, and credentials in one shot. If it doesn't, you've isolated the failure to setup rather than to your application logic.
Resolve from the container, not via facades, in domain code
Facades are convenient at the edges (controllers, commands) but they make unit tests brittle and hide dependencies. Prefer constructor-injecting the package's contract/interface where one exists, and bind the concrete class yourself in a dedicated service provider:
$this->app->bind(YourWrapper::class, fn ($app) => new YourWrapper(
$app->make(\Vendor\Package\Client::class),
));
Wrap it in a thin adapter
Even a one-method wrapper pays for itself at the first major version bump. Your application depends on App\Contracts\Thing, not Vendor\Package\Thing. When v2 renames methods, you edit one file instead of grepping the codebase.
Configure once, at boot
Prefer the published config file over scattered runtime arguments. Anything that differs per environment belongs in config/ reading from env() — and only there, never env() directly in application code (see gotchas).
Integrate at the framework's own seams
$tries, $backoff, and failed() handling. Packages rarely expose retry semantics; you own them.Testing
Use the package's own fake/swap helper if it ships one (Package::fake() is a common convention); otherwise bind a mock in the container inside setUp(). If the package publishes migrations, your test suite needs RefreshDatabase and you should confirm those migrations don't collide with your own table names. For packages with a network client, assert on the outbound request rather than mocking the package internals.
Local iteration
When you need to patch the package, add a path repository to composer.json and develop against a local clone. This is far less painful than editing vendor/ and losing the change on the next composer install.
env() returns null after config:cache
The single most common post-deploy failure with third-party packages. If a package calls env() outside a config file, it works locally and silently breaks in production. Grep the package source for env( — if you find it in src/, either set the values via the config file the package reads, or accept that you cannot use config caching. Test with php artisan config:cache && php artisan config:clear before you ship.
Auto-discovery is not universal
Packages installed with --no-scripts, or in projects with discovery disabled, will throw Target class [...] does not exist. Check the provider is registered before you start debugging the package itself.
Version constraints bite on Laravel majors
A package pinned to illuminate/support:^10.0 will not install on Laravel 11 without a --with-all-dependencies resolution or a fork. Read the constraint before you plan the upgrade, not during it.
Publishing migrations is a one-way door
Once published, the migration lives in your repo and the package's future migrations may assume theirs is unmodified. Publish only if you genuinely need to alter the schema; otherwise let the package load its own.
Facade state leaks between tests
Facade-backed packages often cache resolved instances statically. Call the package's clearResolvedInstance() (or Facade::clearResolvedInstances()) in tearDown, or you'll get order-dependent test failures that vanish when run individually.
Debugging
php artisan about for registration, config:show for config resolution, php artisan event:list for what the package dispatches, and Telescope for the actual queries/HTTP calls it makes. Enable the package's own debug/log channel if it has one — it's usually more informative than your stack trace.
Extension points, in rough order of safety
Don't fight its opinions
If the package wants a specific table name, column shape, or directory layout, adopt it. Working around a package's conventions costs more over a year than the convention ever would, and it makes upstream issues unreportable.
How can I help you explore Laravel packages today?