Laravel Package

Boilerplate Generator

Generate a complete Laravel 12 package boilerplate with package discovery, proper structure, composer.json, README, and all necessary files. Perfect for Laravel developers who want to create modern packages quickly and efficiently.

Laravel Package Generator

Fill out the form below to generate your Laravel package boilerplate

Package Generated Successfully!

Package Ready for Download

Your Laravel package boilerplate has been generated and is ready for download.

Package Name:

License:

Description:

Laravel SaaS Boilerplate

Stack Toast

Laravel Boilerplate

Launch Your SaaS in Days, Not Months

The first Laravel SaaS boilerplate built for vibe coding. 200+ pre-built features, multiple payment processors, and optimized for Cursor.

Laravel 12 Ready
Cursor Optimized
Launch in Days
No Setup Hassles

Everything You Need

200+ Ready Features
Pre-built & tested
100+ AI Models
Integrated & ready
4 Payment Gateways
Stripe, Paddle, Lemon Squeezy, Coinbase
0 Headaches
Just start building

The Complete Guide to Laravel Package Development

Laravel packages are the backbone of the Laravel ecosystem, allowing developers to create reusable, modular components that can be shared across projects. Whether you're building a simple utility package or a complex feature-rich extension, understanding Laravel package development is essential for any serious Laravel developer.

Why Create Laravel Packages? Key Benefits

Understanding the benefits of package development is crucial for motivating developers to adopt this practice. Laravel packages offer numerous advantages that make them essential for modern development workflows.

Reusability

Write once, use everywhere. Packages allow you to create functionality that can be easily integrated into multiple projects, saving time and ensuring consistency across your applications.

Modularity

Break down complex applications into manageable, focused components. Each package handles a specific concern, making your codebase more maintainable and easier to understand.

Version Control

Independent versioning allows you to update packages without affecting other parts of your application. Use semantic versioning to communicate changes clearly to users.

Team Collaboration

Enable team members to work on different packages independently. Share common functionality across projects and teams, fostering better collaboration and code sharing.

Additional Benefits

Security

Isolated packages reduce security risks and make vulnerability management easier.

Performance

Load only what you need, when you need it, improving application performance.

Community

Contribute to the Laravel ecosystem and help other developers solve common problems.

Getting Started with Our Laravel Package Generator

Ready to create your first Laravel package? Our free Laravel Package Boilerplate Generator above makes it incredibly easy to get started. Simply fill out the form with your package details, choose your preferred license, and download a complete, ready-to-use package structure in seconds.

The generated package includes everything you need: proper directory structure, service provider, test files, configuration templates, and comprehensive documentation. No more spending hours setting up the basic structure - focus on implementing your specific functionality while following Laravel best practices.

Quick Start Steps:

  1. Fill out the package generator form above
  2. Download your generated package ZIP file
  3. Extract and customize the package structure
  4. Add your specific functionality
  5. Test and publish your package

What Are Laravel Packages?

Laravel packages are self-contained pieces of functionality that can be easily integrated into Laravel applications. They follow Composer's PSR-4 autoloading standards and can include routes, views, controllers, models, migrations, and any other Laravel components. Packages allow developers to encapsulate functionality, making it reusable across multiple projects and shareable with the community.

The Laravel package ecosystem is vast and diverse, with packages ranging from simple utilities like string helpers to complex systems like payment processors, authentication systems, and content management solutions. Popular packages like Laravel Cashier, Laravel Sanctum, and Laravel Telescope demonstrate the power and flexibility of the Laravel package system.

Package Discovery in Laravel 12

Laravel 12 introduces automatic package discovery, making it easier than ever for users to install and use your packages. Instead of requiring users to manually add your service provider to their bootstrap/providers.php file, you can define the provider in the extra section of your package's composer.json file.

Package Discovery Configuration

Add this to your composer.json to enable automatic discovery:

{
    "extra": {
        "laravel": {
            "providers": [
                "YourVendor\\YourPackage\\ServiceProvider"
            ],
            "aliases": {
                "YourPackage": "YourVendor\\YourPackage\\Facade"
            }
        }
    }
}

Once configured for discovery, Laravel will automatically register your service providers and facades when the package is installed, creating a seamless installation experience for your users. This eliminates the need for manual configuration and reduces installation friction.

Practical Example: Building a PaymentManager Package

Let's walk through creating a real-world package that demonstrates key concepts. We'll build a PaymentManager package that handles different payment gateways, showing how to structure classes, use dependency injection, and implement proper testing.

Package Structure

Our PaymentManager package will have the following structure:

payment-manager/
├── src/
│   ├── PaymentManager.php
│   ├── Contracts/
│   │   └── PaymentGatewayInterface.php
│   ├── Gateways/
│   │   ├── StripeGateway.php
│   │   └── PayPalGateway.php
│   └── ServiceProvider.php
├── config/
│   └── payment-manager.php
├── tests/
│   ├── PaymentManagerTest.php
│   └── TestCase.php
├── composer.json
└── README.md

PaymentGatewayInterface

First, let's define our contract interface:

<?php

namespace PaymentManager\Contracts;

interface PaymentGatewayInterface
{
    public function processPayment(float $amount, array $data): array;
    public function refundPayment(string $transactionId, float $amount): array;
    public function getGatewayName(): string;
}

StripeGateway Implementation

Here's how we implement the Stripe gateway:

<?php

namespace PaymentManager\Gateways;

use PaymentManager\Contracts\PaymentGatewayInterface;

class StripeGateway implements PaymentGatewayInterface
{
    private string $apiKey;
    
    public function __construct(string $apiKey)
    {
        $this->apiKey = $apiKey;
    }
    
    public function processPayment(float $amount, array $data): array
    {
        // Stripe payment processing logic
        return [
            'success' => true,
            'transaction_id' => 'stripe_' . uniqid(),
            'amount' => $amount,
            'gateway' => 'stripe'
        ];
    }
    
    public function refundPayment(string $transactionId, float $amount): array
    {
        // Stripe refund logic
        return [
            'success' => true,
            'refund_id' => 'refund_' . uniqid(),
            'amount' => $amount
        ];
    }
    
    public function getGatewayName(): string
    {
        return 'stripe';
    }
}

PaymentManager Class

The main PaymentManager class that orchestrates different gateways:

<?php

namespace PaymentManager;

use PaymentManager\Contracts\PaymentGatewayInterface;

class PaymentManager
{
    private array $gateways = [];
    private string $defaultGateway;
    
    public function __construct(string $defaultGateway = 'stripe')
    {
        $this->defaultGateway = $defaultGateway;
    }
    
    public function addGateway(string $name, PaymentGatewayInterface $gateway): self
    {
        $this->gateways[$name] = $gateway;
        return $this;
    }
    
    public function processPayment(float $amount, array $data, ?string $gateway = null): array
    {
        $gatewayName = $gateway ?? $this->defaultGateway;
        
        if (!isset($this->gateways[$gatewayName])) {
            throw new \InvalidArgumentException("Gateway '{$gatewayName}' not found");
        }
        
        return $this->gateways[$gatewayName]->processPayment($amount, $data);
    }
    
    public function refundPayment(string $transactionId, float $amount, ?string $gateway = null): array
    {
        $gatewayName = $gateway ?? $this->defaultGateway;
        
        if (!isset($this->gateways[$gatewayName])) {
            throw new \InvalidArgumentException("Gateway '{$gatewayName}' not found");
        }
        
        return $this->gateways[$gatewayName]->refundPayment($transactionId, $amount);
    }
    
    public function getAvailableGateways(): array
    {
        return array_keys($this->gateways);
    }
}

Service Provider Registration

Register the PaymentManager in the service provider:

<?php

namespace PaymentManager;

use Illuminate\Support\ServiceProvider;
use PaymentManager\PaymentManager;
use PaymentManager\Gateways\StripeGateway;
use PaymentManager\Gateways\PayPalGateway;

class PaymentManagerServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(PaymentManager::class, function ($app) {
            $paymentManager = new PaymentManager(
                config('payment-manager.default_gateway', 'stripe')
            );
            
            // Register Stripe gateway
            $paymentManager->addGateway('stripe', new StripeGateway(
                config('payment-manager.stripe.api_key')
            ));
            
            // Register PayPal gateway
            $paymentManager->addGateway('paypal', new PayPalGateway(
                config('payment-manager.paypal.client_id'),
                config('payment-manager.paypal.client_secret')
            ));
            
            return $paymentManager;
        });
    }
    
    public function boot(): void
    {
        $this->publishes([
            __DIR__.'/../config/payment-manager.php' => config_path('payment-manager.php'),
        ], 'payment-manager-config');
    }
}

Usage Example

Here's how users would use the PaymentManager package:

<?php

// In a controller
use PaymentManager\PaymentManager;

class PaymentController extends Controller
{
    public function __construct(private PaymentManager $paymentManager) {}
    
    public function processPayment(Request $request)
    {
        $result = $this->paymentManager->processPayment(
            amount: $request->amount,
            data: $request->all(),
            gateway: $request->gateway // optional, uses default if not specified
        );
        
        if ($result['success']) {
            return response()->json([
                'message' => 'Payment processed successfully',
                'transaction_id' => $result['transaction_id']
            ]);
        }
        
        return response()->json(['error' => 'Payment failed'], 400);
    }
}

Package Initialization and Setup

Before diving into package development, it's crucial to set up your package structure correctly. This section covers the essential steps to initialize a new Laravel package from scratch.

Creating Your Package Directory

Start by creating a dedicated directory for your package. Follow the naming convention: vendor-name/package-name

mkdir mycompany/awesome-package
cd mycompany/awesome-package

# Initialize Git repository
git init
git remote add origin https://github.com/mycompany/awesome-package.git

Composer Configuration

Create a comprehensive composer.json file with proper metadata, autoloading, and dependencies:

{
    "name": "mycompany/awesome-package",
    "description": "An awesome Laravel package for amazing functionality",
    "keywords": ["laravel", "package", "awesome"],
    "license": "MIT",
    "type": "library",
    "require": {
        "php": "^8.2",
        "illuminate/support": "^11.0|^12.0"
    },
    "require-dev": {
        "orchestra/testbench": "^8.0|^9.0",
        "phpunit/phpunit": "^10.0|^11.0"
    },
    "autoload": {
        "psr-4": {
            "MyCompany\\AwesomePackage\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "MyCompany\\AwesomePackage\\Tests\\": "tests/"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "MyCompany\\AwesomePackage\\ServiceProvider"
            ],
            "aliases": {
                "AwesomePackage": "MyCompany\\AwesomePackage\\Facade"
            }
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

Directory Structure Setup

Create the essential directory structure for your package:

mkdir -p src/{Commands,Facades,Middleware,Models}
mkdir -p config
mkdir -p database/migrations
mkdir -p resources/{views,lang}
mkdir -p routes
mkdir -p tests/{Feature,Unit}
mkdir -p public

# Create essential files
touch README.md
touch LICENSE
touch .gitignore
touch phpunit.xml
touch .github/workflows/tests.yml

Git Configuration

Set up proper Git configuration for your package:

# .gitignore
/vendor/
composer.lock
.phpunit.result.cache
.env
.DS_Store
Thumbs.db

# IDE files
.vscode/
.idea/
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

Local Development with Composer Path Repository

During package development, you'll want to test your package in a real Laravel application without publishing it to Packagist. Composer's path repository feature allows you to develop and test packages locally with real-time updates.

Setting Up Path Repository

Add your local package to the test application's composer.json:

{
    "repositories": [
        {
            "type": "path",
            "url": "../my-awesome-package"
        }
    ],
    "require": {
        "mycompany/awesome-package": "*"
    }
}

Development Workflow

Here's the recommended workflow for local package development:

  1. Create Package Structure: Set up your package directory with proper structure
  2. Add to Test App: Add path repository to your test Laravel application
  3. Install Package: Run composer install to symlink the package
  4. Develop & Test: Make changes to your package and test in the application
  5. Real-time Updates: Changes are reflected immediately without reinstallation

Symlink vs Copy

Composer path repositories create symlinks by default, which means changes to your package are immediately reflected in the test application. You can force copying instead:

# Force copying instead of symlinking
composer install --prefer-source

# Or update specific package
composer update mycompany/awesome-package --prefer-source

Testing Your Package

Create a simple test to verify your package works correctly:

<?php

// In your test Laravel application
use MyCompany\AwesomePackage\AwesomePackage;

class PackageTest extends TestCase
{
    public function test_package_can_be_instantiated()
    {
        $package = new AwesomePackage();
        $this->assertInstanceOf(AwesomePackage::class, $package);
    }
    
    public function test_package_functionality()
    {
        $package = new AwesomePackage();
        $result = $package->doSomething();
        
        $this->assertEquals('expected result', $result);
    }
}

Best Practices for Local Development

  • Separate Directories: Keep your package and test application in separate directories
  • Version Control: Use Git for both your package and test application
  • Environment Variables: Use different .env files for package development
  • Testing: Write tests for your package and run them regularly
  • Documentation: Keep README updated as you develop

Types of Laravel Packages

Laravel packages can be categorized into several types based on their functionality and scope:

Service Provider Packages

These packages provide services that extend Laravel's core functionality. They typically include service providers that register services in the application container, configuration files, and the necessary classes to implement the functionality.

Facade Packages

Facade packages provide a static interface to underlying services. They make complex functionality easily accessible through simple, expressive syntax. Examples include Laravel's built-in facades like Cache, DB, and Mail.

Artisan Command Packages

These packages add custom Artisan commands to Laravel applications. They're useful for providing CLI tools for package-specific functionality, such as database seeding, file generation, or maintenance tasks.

Middleware Packages

Middleware packages provide HTTP middleware for request/response processing. They can handle authentication, rate limiting, CORS, logging, and other cross-cutting concerns.

Full-Feature Packages

These comprehensive packages provide complete solutions for specific domains, such as e-commerce, content management, or user management. They typically include models, controllers, views, routes, and migrations.

Package Structure and Organization

A well-structured Laravel package follows established conventions and best practices. The standard package structure includes:

Root Directory Files

  • composer.json: Defines package metadata, dependencies, and autoloading rules
  • README.md: Documentation explaining package purpose, installation, and usage
  • LICENSE: License file specifying usage terms and conditions
  • .gitignore: Specifies files and directories to ignore in version control
  • phpunit.xml: PHPUnit configuration for running tests

Source Directory (src/)

The src directory contains the main package code, organized according to PSR-4 autoloading standards. It typically includes:

  • ServiceProvider.php: Main service provider for package registration
  • Main Package Classes: Core functionality classes
  • Facades/: Facade classes for static access
  • Commands/: Artisan command classes
  • Middleware/: HTTP middleware classes
  • Models/: Eloquent model classes
  • Controllers/: HTTP controller classes

Configuration and Resources

  • config/: Configuration files for package settings
  • database/migrations/: Database migration files
  • database/seeders/: Database seeder classes
  • resources/views/: Blade template files
  • resources/lang/: Language files for localization
  • resources/assets/: CSS, JavaScript, and other assets

Testing Directory (tests/)

The tests directory contains all test files, organized to mirror the src directory structure. It includes:

  • TestCase.php: Base test case class with package-specific setup
  • Unit Tests: Tests for individual classes and methods
  • Feature Tests: Tests for complete features and workflows
  • Integration Tests: Tests for package integration with Laravel

Service Providers: The Heart of Laravel Packages

Service providers are the foundation of Laravel packages. They handle package registration, service binding, and configuration loading. Understanding service providers is crucial for effective package development.

Service Provider Lifecycle

Laravel service providers have a specific lifecycle with two main methods:

  • register(): Called first, used for binding services into the container
  • boot(): Called after all providers are registered, used for event listeners, middleware, and other setup

Best Practices for Service Providers

  • Keep the register() method focused on service binding
  • Use deferred providers for services that aren't always needed
  • Implement proper error handling and validation
  • Use configuration files for customizable options
  • Provide clear documentation for all registered services

Package Resources: Configuration, Routes, Views, and More

Laravel packages can include various types of resources that integrate seamlessly with the application. Understanding how to properly register and publish these resources is crucial for creating professional packages.

Configuration Files

Package configuration files allow users to customize your package's behavior. Use the mergeConfigFrom() method to merge your package's default configuration with the user's published configuration:

public function boot(): void
{
    $this->mergeConfigFrom(
        __DIR__.'/../config/package.php', 'package'
    );
}

Routes

Register package routes using the loadRoutesFrom() method. This allows your package to define its own routes that integrate with the application:

public function boot(): void
{
    $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
    $this->loadRoutesFrom(__DIR__.'/../routes/api.php');
}

Database Migrations

Package migrations are automatically loaded by Laravel. Use the loadMigrationsFrom() method to register your package's migrations:

public function boot(): void
{
    $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
}

Language Files

Package language files can be loaded using the loadTranslationsFrom() method, enabling localization support:

public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'package');
}

Views and Blade Components

Package views can be registered using loadViewsFrom(), and Blade components can be registered with componentNamespace():

public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'package');
    
    Blade::componentNamespace('Package\\Views\\Components', 'package');
}

About Artisan Command

Laravel 12's about command provides application information. Packages can add their own information using the AboutCommand class:

use Illuminate\Foundation\Console\AboutCommand;

public function boot(): void
{
    AboutCommand::add('My Package', fn () => [
        'Version' => '1.0.0',
        'Status' => 'Active'
    ]);
}

Artisan Commands and Optimization

Laravel packages can register custom Artisan commands and integrate with Laravel's optimization system for better performance.

Registering Commands

Use the commands() method to register your package's Artisan commands:

public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            InstallCommand::class,
            PublishCommand::class,
        ]);
    }
}

Optimization Commands

Laravel 12 allows packages to register commands that run during optimization. Use the optimizes() method:

public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->optimizes(
            optimize: 'package:optimize',
            clear: 'package:clear-optimizations',
        );
    }
}

Public Assets and Publishing

Packages often need to publish assets like CSS, JavaScript, and images to the application's public directory. Laravel provides a robust system for managing and publishing these assets.

Publishing Assets

Use the publishes() method to define publishable assets with tags for easy management:

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

Publishing Migrations

Use the publishesMigrations() method for database migrations:

public function boot(): void
{
    $this->publishesMigrations([
        __DIR__.'/../database/migrations/' => database_path('migrations')
    ], 'migrations');
}

Package Configuration and Customization

Well-designed packages provide configuration options that allow users to customize behavior without modifying the package code. Laravel's configuration system makes this straightforward.

Configuration File Structure

Package configuration files should be placed in the config directory and follow Laravel's configuration conventions. They should include:

  • Default values for all configuration options
  • Clear documentation for each option
  • Validation rules where applicable
  • Environment-specific overrides

Publishing Configuration

Packages should provide the ability to publish configuration files to the application's config directory, allowing users to customize settings. This is typically done through the service provider's boot() method using the publishes() method.

Database Integration in Packages

Many Laravel packages require database integration for storing data, managing relationships, and providing persistence. Understanding how to properly integrate database functionality is essential for package development.

Migrations

Package migrations should be designed to be non-destructive and reversible. They should include proper foreign key constraints, indexes, and data validation. Packages should provide commands to publish and run migrations.

Models and Relationships

Package models should follow Laravel conventions and provide clear relationships with application models. They should include proper validation, scopes, and accessors/mutators as needed.

Seeders

Package seeders can provide sample data or essential data for package functionality. They should be optional and clearly documented for users who want to use them.

Automated Testing Setup

Setting up automated testing is essential for package quality and reliability. This section covers both PHPUnit and Pest testing frameworks, along with proper test environment configuration.

PHPUnit Configuration

Create a comprehensive phpunit.xml configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory>tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory>tests/Feature</directory>
        </testsuite>
    </testsuites>
    <source>
        <include>
            <directory>src</directory>
        </include>
    </source>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="APP_KEY" value="base64:YourAppKeyHere"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
    </php>
</phpunit>

TestCase Base Class

Create a base TestCase class using Orchestra Testbench:

loadLaravelMigrations();
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
    }

    protected function getPackageProviders($app)
    {
        return [
            ServiceProvider::class,
        ];
    }

    protected function getEnvironmentSetUp($app)
    {
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => '',
        ]);
    }
}

Pest Testing Framework

For a more expressive testing experience, consider using Pest. Add it to your composer.json:

{
    "require-dev": {
        "pestphp/pest": "^2.0",
        "pestphp/pest-plugin-laravel": "^2.0"
    }
}

Create a Pest.php configuration file:

in('Feature', 'Unit');

Testing Laravel Packages

Comprehensive testing is crucial for package reliability and maintainability. Laravel provides excellent testing tools that work seamlessly with packages.

Test Environment Setup

Package tests should use Orchestra Testbench, which provides a Laravel application instance specifically for testing packages. This ensures tests run in a controlled environment that mimics real Laravel applications.

Testing Strategies

  • Unit Tests: Test individual classes and methods in isolation
  • Integration Tests: Test package integration with Laravel components
  • Feature Tests: Test complete workflows and user interactions
  • Performance Tests: Ensure package doesn't significantly impact application performance

Test Coverage

Aim for high test coverage, focusing on critical functionality and edge cases. Use tools like PHPUnit's code coverage reports to identify untested code paths.

CI/CD Configuration for Automated Deployments

Setting up continuous integration and deployment ensures code quality and facilitates automated package releases. This section covers GitHub Actions configuration for Laravel packages.

GitHub Actions Workflow

Create a comprehensive CI/CD workflow in .github/workflows/tests.yml:

name: Tests

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  tests:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        php: [8.2, 8.3]
        laravel: [11.*, 12.*]
        
    name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: ${{ matrix.php }}
        extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
        coverage: xdebug
        
    - name: Get composer cache directory
      id: composer-cache
      run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
      
    - name: Cache composer dependencies
      uses: actions/cache@v3
      with:
        path: ${{ steps.composer-cache.outputs.dir }}
        key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
        restore-keys: ${{ runner.os }}-composer-
        
    - name: Install dependencies
      run: composer install --prefer-dist --no-progress --no-suggest
      
    - name: Execute tests
      run: vendor/bin/phpunit --coverage-clover coverage.xml
      
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml
        flags: unittests
        name: codecov-umbrella

Automated Release Workflow

Create an automated release workflow in .github/workflows/release.yml:

name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: 8.2
        extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
        
    - name: Install dependencies
      run: composer install --prefer-dist --no-progress --no-suggest
      
    - name: Run tests
      run: vendor/bin/phpunit
      
    - name: Create Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: Release ${{ github.ref }}
        draft: false
        prerelease: false

Code Quality Tools

Add code quality tools to your CI pipeline for better code standards:

# Add to composer.json require-dev
{
    "require-dev": {
        "squizlabs/php_codesniffer": "^3.7",
        "phpstan/phpstan": "^1.10",
        "laravel/pint": "^1.0"
    }
}

# Add to CI workflow
- name: Run PHP CS Fixer
  run: vendor/bin/php-cs-fixer fix --dry-run --diff

- name: Run PHPStan
  run: vendor/bin/phpstan analyse

- name: Run Laravel Pint
  run: vendor/bin/pint --test

Package Documentation and Support

Excellent documentation is essential for package adoption and success. Users need clear, comprehensive documentation to understand how to install, configure, and use your package.

README.md Best Practices

  • Clear package description and purpose
  • Installation instructions with code examples
  • Configuration options and examples
  • Usage examples and common use cases
  • API documentation for public methods
  • Contributing guidelines
  • License information
  • Changelog and version history

Code Documentation

All public methods and classes should have comprehensive PHPDoc comments explaining their purpose, parameters, return values, and any exceptions they might throw.

Package Publishing and Distribution

Once your package is complete and tested, you need to make it available to the community. Packagist is the primary repository for PHP packages, including Laravel packages.

Packagist Submission

  • Create a Packagist account and submit your package
  • Ensure your composer.json is properly configured
  • Add appropriate tags and keywords for discoverability
  • Set up automatic updates from your Git repository

Version Management

Use semantic versioning (SemVer) for your package releases. This helps users understand the impact of updates and makes dependency management easier.

Publishing to Packagist: Complete Guide

Publishing your package to Packagist makes it available to the entire PHP community. This comprehensive guide covers everything from account setup to automated publishing.

Step 1: Packagist Account Setup

Create a Packagist account and connect it to your GitHub account for seamless integration:

  1. Visit packagist.org and create an account
  2. Connect your GitHub account for automatic package updates
  3. Verify your email address to enable package submission
  4. Set up your profile with proper information

Step 2: Package Preparation

Ensure your package is ready for publication with proper metadata and structure:

# Verify your composer.json is complete
composer validate

# Run tests to ensure everything works
vendor/bin/phpunit

# Check code quality
vendor/bin/phpstan analyse
vendor/bin/pint --test

# Create your first release tag
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0

Step 3: Submit to Packagist

Submit your package to Packagist using the repository URL:

  1. Go to your Packagist dashboard
  2. Click "Submit" and enter your repository URL
  3. Verify package information and metadata
  4. Submit for review and approval

Step 4: Automated Updates

Set up automatic updates from GitHub to Packagist:

# In your package's Packagist settings:
# 1. Enable "Auto-update" 
# 2. Set up GitHub webhook (if not automatic)
# 3. Configure update frequency (recommended: immediate)

# For manual updates, use the Packagist API:
curl -X POST https://packagist.org/api/update-package?username=YOUR_USERNAME&apiToken=YOUR_TOKEN \
  -d '{"repository":{"url":"https://github.com/yourusername/your-package"}}'

Step 5: Package Maintenance

Maintain your package with regular updates and community engagement:

  • Regular Updates: Keep dependencies up to date
  • Bug Fixes: Respond quickly to issues and pull requests
  • Documentation: Keep README and documentation current
  • Version Tags: Use semantic versioning for releases
  • Community: Engage with users and contributors

Packagist Best Practices

Follow these best practices for successful package publishing:

  • Clear Naming: Use descriptive, unique package names
  • Comprehensive README: Include installation, usage, and examples
  • Proper Licensing: Choose appropriate open-source license
  • Keywords: Add relevant keywords for discoverability
  • Stable Releases: Mark stable versions appropriately
  • Security: Keep packages secure and up-to-date

Advanced Package Development Techniques

As you become more experienced with package development, you can implement advanced techniques to create more powerful and flexible packages.

Event-Driven Architecture

Use Laravel's event system to create loosely coupled, extensible packages. Events allow other packages or applications to hook into your package's functionality without modifying the core code.

Package Dependencies and Conflicts

Properly manage package dependencies in composer.json. Use version constraints to ensure compatibility while allowing for updates. Handle conflicts gracefully when multiple packages provide similar functionality.

Performance Optimization

  • Use deferred service providers for optional services
  • Implement lazy loading for expensive operations
  • Cache configuration and other frequently accessed data
  • Optimize database queries and relationships
  • Minimize memory usage and startup time

Common Package Development Pitfalls

Understanding common mistakes can help you avoid them and create better packages from the start.

Over-Engineering

Avoid creating overly complex packages when simpler solutions would suffice. Focus on solving specific problems well rather than trying to be everything to everyone.

Poor Error Handling

Implement comprehensive error handling and provide meaningful error messages. Users should understand what went wrong and how to fix it.

Inadequate Testing

Don't skip testing or write only superficial tests. Comprehensive testing prevents bugs and makes refactoring safer.

Breaking Changes

Avoid breaking changes in minor or patch releases. Use deprecation warnings and gradual migration paths for major changes.

Package Maintenance and Updates

Package development doesn't end with the initial release. Ongoing maintenance is crucial for long-term success and user satisfaction.

Regular Updates

  • Keep dependencies up to date
  • Fix bugs and security issues promptly
  • Add new features based on user feedback
  • Maintain compatibility with new Laravel versions

Community Engagement

Engage with your package's user community through GitHub issues, discussions, and social media. User feedback is invaluable for improving your package.

Security Considerations

Regularly audit your package for security vulnerabilities. Use tools like GitHub's Dependabot to monitor dependencies for security issues.

Frequently Asked Questions

Is this Laravel package generator really free to use?

Yes, our Laravel package boilerplate generator is completely free to use. There are no hidden fees, subscriptions, or premium tiers. You can generate as many packages as you need without any restrictions.

Do I need to create an account to use the generator?

No account creation is required. You can start generating Laravel packages immediately without any registration process. Simply fill out the form and download your package boilerplate.

What Laravel versions are supported by the generated packages?

The generated packages are compatible with Laravel 12, the latest version, using PHP 8.2 or higher. The packages follow Laravel 12 conventions and best practices, including automatic package discovery, proper service provider structure, and modern Laravel features.

What license options are available?

We support all major open-source licenses including MIT, Apache 2.0, GPL v3, AGPL v3, LGPL v3, Mozilla Public License 2.0, Boost Software License 1.0, and The Unlicense.

What files are included in the generated package?

The generated package includes a complete Laravel 12 package structure with composer.json (with package discovery), README.md, LICENSE file, service provider, main package class, test files, PHPUnit configuration, configuration files, routes, migrations, views, and .gitignore file.

Does the generator include Laravel 12 package discovery?

Yes! The generated packages include automatic package discovery configuration in composer.json, so users don't need to manually register service providers. The package will be automatically discovered and registered when installed via Composer.

Does the generator include testing setup and CI/CD configuration?

Yes! The generated packages include comprehensive testing setup with PHPUnit and Pest support, GitHub Actions workflows for CI/CD, code quality tools (PHPStan, Laravel Pint), and automated release workflows for seamless package publishing.

How can I test my package locally during development?

Use Composer's path repository feature to test your package in a real Laravel application. Add your local package path to the test application's composer.json repositories section, and Composer will create a symlink for real-time development and testing.

Does the guide include practical examples?

Yes! Our guide includes a complete PaymentManager package example that demonstrates real-world package development, including interfaces, implementations, service providers, and usage examples. This helps you understand how to structure and implement your own packages.

Can I customize the generated package after downloading?

Absolutely! The generated package is a starting point that you can fully customize. Add your specific functionality, modify the structure, and adapt it to your needs.

Are there any usage limits or rate limits?

We implement a rate limit of 3 requests per minute per IP address to prevent abuse and ensure fair usage for all users. This is sufficient for normal development needs.

Is my package data secure and private?

Yes, we take data security seriously. Your package information is processed securely and is not stored on our servers. We use industry-standard security measures and the data is only used to generate your package.

What if I encounter an error while generating a package?

If you experience any issues, please check that all required fields are filled out correctly and try again. For persistent problems, contact our support team through the contact form on our main website.

Can I use the generated packages commercially?

Yes, you can use the generated packages for any purpose, including commercial projects. The license you choose during generation will determine the specific terms and conditions for your package.

How do I install and use the generated package?

After downloading, extract the ZIP file and follow the instructions in the README.md file. Typically, you'll need to add the package to your Laravel application's composer.json and register the service provider.

Can I contribute to improving this generator?

We welcome contributions! If you have suggestions for improvements or find bugs, please contact us through our main website. We're always looking to make the generator better for the Laravel community.