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

Package Skeleton Laravel Laravel Package

zing/package-skeleton-laravel

zing/package-skeleton-laravel is a ready-to-use starting point for building Laravel packages. It provides sensible defaults, service provider scaffolding, configuration publishing, and test setup so you can skip boilerplate and focus on shipping your package.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a skeleton/template (zingimmick/package-skeleton-laravel), not a runtime library — you don't composer require it into an app, you generate a new repository from it and then live inside that repo. Version 3.5.0 is a tooling/compatibility release (PHP 8.5, PHPUnit 12, Laravel 13, newer orchestra/testbench constraint), so the "getting started" flow is unchanged, but what you get out of the box is now current with the newest Laravel/PHP matrix.

Minimal path:

# 1. Create your package repo from the template (GitHub "Use this template")
git clone [email protected]:you/your-package.git && cd your-package

# 2. Install deps and confirm the baseline is green before you touch anything
composer install
composer test          # or: vendor/bin/phpunit / vendor/bin/pest

# 3. Bulk-rename the skeleton placeholders (see Gotchas — this is the step people rush)

Where to look first, in order:

  1. composer.json — package name, autoload.psr-4 namespace, require/require-dev constraints, extra.laravel.providers / aliases.
  2. src/ — the skeleton service provider is the entry point; everything you build hangs off its register()/boot().
  3. config/ — the package config file and how it's merged/published.
  4. tests/ — the Testbench-based TestCase and the example test. This is the part whose behaviour changed most in 3.5.0 (PHPUnit 12 / Testbench constraint), so read it before adding tests.
  5. .github/workflows/ — the CI matrix that now targets PHP 8.5 and Laravel 13.

First real use case: build a package that registers one Artisan command and one publishable config file, then prove it works from a consuming Laravel app. That exercises autoloading, provider discovery, config merging, and the test harness in one pass — the four things that break first.

Implementation Patterns

Rename-then-verify workflow. The template ships with placeholder vendor/namespace strings. Do the rename as a single mechanical commit (package-skeleton-laravel → your-vendor/your-package, Zingimmick\PackageSkeletonLaravel → YourVendor\YourPackage, author metadata, license year), then immediately run composer dump-autoload and composer test. Do not mix the rename with your first feature — you want a clean diff to bisect if autoloading breaks.

Service provider as the integration seam. Register bindings in register(), and keep boot() for publishable assets, migrations, commands, and Blade/components. Guard optional integrations with class_exists()/$this->app->runningInConsole() rather than assuming a full app:

public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/your-package.php' => config_path('your-package.php'),
    ], 'your-package-config');

    if ($this->app->runningInConsole()) {
        $this->commands([YourCommand::class]);
    }
}

Merge defaults, then read through config. Use mergeConfigFrom() so consumers can override a subset. Never read env() inside package code outside the config file — config caching will silently return null.

Test with Testbench, not a full app. Package tests run through orchestra/testbench; 3.5.0's constraint bump means you should keep your testbench version aligned with the Laravel versions you claim to support. Pattern:

// tests/TestCase.php extends Orchestra\Testbench\TestCase
protected function getPackageProviders($app): array
{
    return [YourPackageServiceProvider::class];
}

For each supported Laravel major you want to prove, drive it through the CI matrix rather than local branch juggling — the workflows shipped in the template already encode the PHP/Laravel combinations, and that matrix is exactly what 3.5.0 refreshed.

Feature-test the public surface. Hit the facade/command/HTTP route the package exposes; assert config defaults resolve, publishes land in the right paths, and commands are discoverable via $this->artisan(...).

Integration tip — pin the skeleton generation, not the skeleton. Because the template is consumed once, there's no composer update path to pick up 3.5.0. If you want its new CI/PHP 8.5/Laravel 13 support in an existing package, diff the template's .github/workflows/, composer.json dev constraints, and phpunit.xml against yours and port them manually.

Gotchas and Tips

  • The version number tells you nothing about your package. 3.5.0 is almost entirely dependency bumps and compatibility additions (PHPUnit 12, PHP 8.5, Laravel 13, Testbench constraint, CI action bumps). No public API of the skeleton changed. Treat it as a maintenance signal, not a migration event.
  • CI action bumps are breaking in disguise. actions/checkout moving 4 → 5 → 6 and ramsey/composer-install 3 → 4 can change default inputs (Node runtime, cache behaviour, composer-options handling). If you backport the workflows, read those action changelogs — a green local test suite says nothing about a broken workflow.
  • Placeholder renames silently miss things. Namespace strings appear in composer.json, the provider, facades, tests, README.md, CHANGELOG.md, and .github/. Search case-insensitively for both the vendor and namespace forms; a missed PSR-4 path usually surfaces only as a Class not found in CI, not locally (case-insensitive filesystems hide it).
  • PHPUnit 12 is stricter. Newer PHPUnit deprecates docblock-metadata annotations (@test, @dataProvider, @covers) in favour of attributes. If you merge the 3.5.0 tooling into a package with docblock-annotated tests, expect noisy deprecations or outright failures — convert to #[Test], #[DataProvider], #[CoversClass].
  • PHP 8.5 raises the deprecation floor. Bumping the dev environment to 8.5 makes implicit-nullable and other deprecations visible in your own source. Run the suite under the highest PHP in your matrix locally before publishing; deprecations you don't see on 8.2 will hit your users.
  • Don't over-claim the matrix. Declaring laravel/framework: ^10|^11|^12|^13 in a package you only test on 12 and 13 is a support lie. Let the CI matrix define what you assert, and let composer.json reflect exactly that.
  • mergeConfigFrom runs on every boot. Keep the config file free of side effects (no service resolution, no I/O) — it executes even for consumers who published their own copy and expect overrides to win.
  • Test the publish paths. It's easy to ship a publishes() tag that's typo'd; add a test asserting the tag exists and the destination resolves, otherwise consumers only find out during vendor:publish.
  • Extension points worth pre-wiring: a Facade over a bound singleton (easy to fake in tests), an interfaces-first contract so consumers can swap implementations via container binding, and Macroable on anything users might want to extend without forking.
  • Debugging package discovery: php artisan about and php artisan package:discover show whether your provider was auto-registered from extra.laravel.providers. If commands or config are missing but tests pass, discovery — not your code — is usually the culprit.
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.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json