PagibleAI is split into Composer packages, so you can ship only the CMS capabilities your Laravel application needs. You can create a dependency-only metapackage or an installable distribution library with its own Laravel provider and setup command. Neither approach requires the full aimeos/pagible meta-package.
Build Custom PagibleAI Distributions
Compatibility: The examples use ~0.13 for compatible PagibleAI 0.13+ packages. Keep every PagibleAI dependency in one compatible series.
Choose the distribution type
composer.json only; no PHP files or Laravel providerChoose PagibleAI packages
The aimeos/pagible meta-package currently bundles Core, Admin, AI, GraphQL, Search, JSON:API, MCP and Theme. Backup, Cashier with its payment adapters, Import, Pulse and the theme packages are separate opt-in packages; Webhooks and CDN are optional packages the meta-package suggests. None of these opt-in packages is contained in the aimeos/pagible download, so require each one explicitly. The PagibleAI dependencies in the table are required; Composer resolves them transitively.
aimeos/pagible-coreaimeos/pagible-adminaimeos/pagible-graphqlaimeos/pagible-themeaimeos/pagible-aiaimeos/pagible-searchaimeos/pagible-jsonapiaimeos/pagible-mcpaimeos/pagible-backupaimeos/pagible-cashieraimeos/pagible-cashier-stripe, aimeos/pagible-cashier-paddle or aimeos/pagible-cashier-mollieaimeos/pagible-importaimeos/pagible-pulseaimeos/pagible-themes-bold, -estate, -glass, -journal, -luxury, -news, -pagible, -paper, -premium, -style or -tasteaimeos/pagible-webhooksaimeos/pagible-cdnStart from a common profile
aimeos/pagible-themes-* packagesaimeos/pagible-cashier-stripe, -paddle or -mollieUse PagibleAI GraphQL API for the management API and PagibleAI JSON REST API for read-only delivery. If your distribution owns presentation or editor features, continue with Create a PagibleAI Theme Package or Build Admin Extensions for PagibleAI CMS.
Create a dependency-only metapackage
A Composer metapackage contains no PHP files, so it cannot register a Laravel provider or installer. Use it when each application can run the selected PagibleAI setup commands itself.
{
"name": "your-vendor/headless-cms",
"description": "Headless CMS distribution built on PagibleAI",
"type": "metapackage",
"license": "MIT",
"require": {
"php": "^8.2",
"aimeos/pagible-core": "~0.13",
"aimeos/pagible-graphql": "~0.13",
"aimeos/pagible-jsonapi": "~0.13"
}
}
After requiring the metapackage, run the installers for its selected modules and migrate the application database:
composer require your-vendor/headless-cms
php artisan cms:install:core
php artisan cms:install:graphql
php artisan cms:install:jsonapi
php artisan migrate
Create an installable distribution
Use a Laravel library when you need configuration, custom PHP code or one setup command. A small distribution package can use this structure:
your-cms/
├── composer.json
├── config/
│ └── distribution.php
└── src/
├── ServiceProvider.php
└── Commands/
└── Install.php
Define composer.json
{
"name": "your-vendor/your-cms",
"description": "Installable CMS distribution built on PagibleAI",
"type": "library",
"license": "MIT",
"require": {
"php": "^8.2",
"aimeos/pagible-core": "~0.13",
"aimeos/pagible-graphql": "~0.13",
"aimeos/pagible-jsonapi": "~0.13"
},
"autoload": {
"psr-4": {
"YourVendor\\YourCms\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"YourVendor\\YourCms\\ServiceProvider"
]
}
}
}
Register the provider
Laravel discovers this provider through composer.json. Merge configuration defaults during register(). Register console commands and publishable files during boot(). Remove the configuration calls if your distribution does not ship config/distribution.php.
<?php
namespace YourVendor\YourCms;
use Illuminate\Support\ServiceProvider as Base;
use YourVendor\YourCms\Commands\Install;
class ServiceProvider extends Base
{
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([Install::class]);
$this->publishes([
__DIR__ . '/../config/distribution.php'
=> config_path('distribution.php'),
], 'your-cms-config');
}
}
public function register(): void
{
$this->mergeConfigFrom(
__DIR__ . '/../config/distribution.php',
'distribution'
);
}
}
Register the installer
Without aimeos/pagible, the top-level cms:install command is unavailable. Register your own command instead. This example installs the headless profile, checks that each package installer exists and identifies a missing or failed command. Adjust $commands to your selected modules and keep dependency setup before dependent packages. Run php artisan migrate after it completes:
<?php
namespace YourVendor\YourCms\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use YourVendor\YourCms\ServiceProvider;
class Install extends Command
{
protected $signature = 'cms:install:your-cms';
protected $description = 'Install the custom PagibleAI distribution';
public function handle(): int
{
$commands = [
'cms:install:core',
'cms:install:graphql',
'cms:install:jsonapi',
];
$available = Artisan::all();
foreach ($commands as $command) {
if (!isset($available[$command])) {
$this->error("Missing installer: {$command}");
return self::FAILURE;
}
if ($this->call($command) !== self::SUCCESS) {
$this->error("Installer failed: {$command}");
return self::FAILURE;
}
}
if ($this->call('vendor:publish', [
'--provider' => ServiceProvider::class,
'--tag' => 'your-cms-config',
]) !== self::SUCCESS) {
$this->error('Publishing distribution config failed.');
return self::FAILURE;
}
$this->info('Custom PagibleAI distribution installed.');
return self::SUCCESS;
}
}
Use the available setup commands
cms:install:corecms:install:admincms:install:graphqlcms:install:aicms:install:searchcms:install:jsonapicms:install:mcpcms:install:themecms:install:cashier after installing exactly one adapter, then cms:cashier:checkcms:install:pulsecms:install:webhooks, then cms:webhooks:check on every deployBackup, CDN, Import and the theme packages do not register cms:install:* commands. Backup provides cms:backup and cms:restore; Import provides cms:wp-import and cms:t3-import; theme packages only need php artisan vendor:publish --tag=cms-theme, and cms:demo --theme=<name> seeds their optional demo content; CDN is configured with php artisan vendor:publish --provider="Aimeos\Cms\CdnServiceProvider" and provides cms:cdn:purge for manual purges. The top-level cms:install command belongs to aimeos/pagible and auto-discovers registered package installers.
Core provides cms:previews, which creates missing preview images after you change cms.image.preview-sizes and replaces all previews with --force, e.g. after changing the image driver, format or quality.
CDN purges and webhook deliveries run as queued jobs, so a distribution that includes them needs a queue worker (php artisan queue:work). CDN purges use the CMS queue (CMS_QUEUE_CONNECTION, CMS_QUEUE); webhooks use their own queue (CMS_WEBHOOKS_QUEUE_CONNECTION, CMS_WEBHOOKS_QUEUE, default cms-webhooks).
Validate the distribution
Run these checks in the distribution package before you tag it:
composer validate --strict
composer update
php -l src/ServiceProvider.php
php -l src/Commands/Install.php
Install the package in a clean Laravel application, run its installer, migrate the database and verify the selected admin or API endpoints. Automated tests are optional, but add them when your provider or installer contains package-specific behavior.
References
Current implementation references: the PagibleAI meta-package manifest, the Admin dependency manifest, AI dependency manifest, Webhooks dependency manifest, CDN dependency manifest and the meta-package install command.
Review these linked manifests whenever you change the supported PagibleAI series or add a module to the distribution.
Troubleshooting FAQ
Why is `cms:install:your-cms` missing?
Run composer dump-autoload, confirm Laravel package discovery lists your service provider and check that boot() calls $this->commands([Install::class]) while the application runs in the console.
Why is a selected package installer missing?
Confirm the package is present with composer show 'aimeos/pagible-*'. Composer must install the package and Laravel must discover its provider before its command is registered.
Why does `cms:install` not exist?
The top-level command comes from aimeos/pagible. A custom distribution that omits that meta-package must use its own installer or run each cms:install:* command directly.
Why does vendor:publish copy nothing?
Make sure the provider's $this->publishes() mapping uses the same tag passed by your installer. Remove the publish call when your distribution has no configuration or assets.
Why does Composer reject the selected modules?
Keep all PagibleAI packages on the same compatible series, then run composer why-not aimeos/pagible-core ~0.13 to find the conflicting constraint.
Why does the Admin panel load without a working API?
Include GraphQL, run cms:install:graphql before cms:install:admin, migrate the database and clear Laravel's configuration and route caches.
Why does `cms:install:cashier` fail with a provider error?
Install exactly one of aimeos/pagible-cashier-stripe, aimeos/pagible-cashier-paddle or aimeos/pagible-cashier-mollie. The installer stops when no adapter or more than one is installed.