Easy, flexible and powerful cloud-native Laravel CMS package powered by AI with JSON:API, GraphQL API, templates, and themes
See the codeThe easy, flexible and scalable API-first PagibleAI CMS package for Laravel.
PagibleAI CMS is an API-first content management system that can be installed into any existing Laravel application. It combines the ease of use of WordPress with the structured content management capabilities of Contentful, powered by AI for content generation, image manipulation, and translation.
Whether you need a simple blog or a multi-tenant, multi-domain CMS serving millions of pages, PagibleAI scales to your needs — from a single SQLite-backed page to database clusters.
| Technology | Purpose |
|---|---|
| PHP 8.2+ | Backend language |
| Laravel 11.x / 12.x / 13.x | Web framework |
| Vue.js 3 | Admin panel frontend |
| Vuetify | Admin UI component library |
| Lighthouse | GraphQL API |
| Prism / Prisma PHP | AI/LLM integration |
| Vite | Frontend build tool |
PagibleAI CMS is a modular monorepo split into focused sub-packages. Each package handles a specific concern and can be used independently:
Pages are organized as a nested set tree (using _lft/_rgt columns). All content changes are tracked as immutable version snapshots — editors see the latest draft while the public sees the published version. Caching is per-page with configurable duration.
pagible/
├── src/ Meta-package (install orchestrator + serve command)
├── core/ Models, permissions, tenancy, utilities, migrations
├── admin/ Vue.js admin panel (Vuetify + Vite)
├── ai/ AI features (Prism / Prisma PHP)
├── graphql/ GraphQL API (Lighthouse)
├── backup/ Backup and restore
├── cashier/ Shared payment-backed frontend access
├── cashier-*/ Stripe, Paddle, and Mollie Cashier adapters
├── import/ CMS importers (WordPress, etc.)
├── search/ Full-text search (Laravel Scout)
├── jsonapi/ Read-only JSON:API
├── mcp/ MCP server (30+ tools)
├── theme/ Frontend rendering (Blade templates)
├── themes/ Frontend themes (CSS)
├── tests/ Shared test infrastructure
├── config/ Configuration files
└── phpunit.xml Aggregated test runner
If you don't have an existing Laravel application, create one first:
composer create-project laravel/laravel pagible
cd pagible
Then install PagibleAI CMS:
composer req aimeos/pagible
php artisan cms:install
php artisan migrate
Fresh Laravel applications contain a static public/robots.txt file. Web servers
serve that file before Laravel receives the request. If it contains custom rules,
first copy them into the robots.txt configuration element on the root page and
publish the change. Then remove the static file to enable Pagible's dynamic route:
rm public/robots.txt
The dynamic route serves the published rules together with the generated sitemap
and news sitemap URLs. Alternatively, configure the web server to pass
/robots.txt to Laravel even when the static file exists.
Now, adapt the .env file of your application and change the APP_URL setting to your domain. If you are using php artisan serve for testing, add the port of the internal web server (APP_URL=http://localhost:8000). Otherwise, the uploading files will fail because they wouldn't be loaded!
Add a line in the "post-update-cmd" section of your composer.json file to update the admin backend files after each update:
"post-update-cmd": [
"@php artisan vendor:publish --force --tag=cms-admin --tag=cms-graphql",
"@php artisan vendor:publish --tag=cms-theme",
"@php artisan migrate",
...
],
To allow users to edit CMS content or to create a new users if they don't exist yet, you can use the cms:user command (replace the e-mail address by the users one):
php artisan cms:user -e editor@example.com
This adds admin privileges for the specified user. For more information regarding authorization and permissions, please have a look into the authorization and permission page.
The CMS admin backend is available at (replace "mydomain.tld" with your own one):
http://mydomain.tld/cmsadmin
Install exactly one Pagible Cashier provider in the Laravel application that already contains Pagible CMS:
composer require aimeos/pagible-cashier-stripe
# or: aimeos/pagible-cashier-paddle
# or: aimeos/pagible-cashier-mollie
php artisan cms:install:cashier
For Stripe, an interactive installer offers to create the webhook when
APP_URL, STRIPE_KEY, and STRIPE_SECRET are ready. Automated installations
must opt in with --webhook.
Add Pagible's CashierAccess trait and the selected provider's Billable trait
to the application user model. Then configure the provider credentials and
verified webhooks, define a frontend access value such as premium-members, and
run the local readiness check:
php artisan cms:cashier:check
Use that same access value in both places in the CMS admin:
pricing element to a public sales page and select premium-members as
the package's frontend access role. Add a subscription price, a one-time
price, or both, then publish the pricing content.premium-members, and apply the change.Verified payment webhooks grant and revoke the role automatically. A successful one-time payment grants permanent access unless it is fully refunded or charged back. A subscription grants access through its provider-confirmed paid period. See the Pagible Cashier guide for the user-model example, access-catalog setup, provider-specific price fields, webhook configuration, private files, cancellations, and an end-to-end checklist.
File uploads use the Laravel disk configured by CMS_DISK and are public by default. Set
CMS_PRIVATE_DISK to a different, non-public Laravel disk to enable the translated
“Protect with page access” option in file fields. Temporary URLs generated by remote private
disks expire after CMS_PRIVATE_TTL seconds (300 by default); local private files are streamed
through the access-controlled CMS route.
To generate texts/images from prompts, analyze image/video/audio content, or execute actions based on your prompts, you have to configure one or more of the AI service providers supported by the Prism and Prisma packages.
Note: You only need to configure API keys for the AI service providers you are using, not for all!
All service providers require to sign-up and create an account first. They will provide
an API key which you need to add to your .env file or as environment variable, e.g.:
GEMINI_API_KEY="..."
OPENAI_API_KEY="..."
CLIPDROP_API_KEY="..."
DEEPL_API_KEY="..."
# Text translation
CMS_AI_TRANSLATE_API_KEY="${DEEPL_API_KEY}"
# For DeepL Pro accounts
# CMS_AI_TRANSLATE_URL="https://api.deepl.com/"
# Analyze content and generate text/images
CMS_AI_REFINE_API_KEY="${OPENAI_API_KEY}"
CMS_AI_WRITE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_DESCRIBE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_IMAGINE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_INPAINT_API_KEY="${GEMINI_API_KEY}"
CMS_AI_REPAINT_API_KEY="${GEMINI_API_KEY}"
# Image manipulation
CMS_AI_ERASE_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_ISOLATE_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_UNCROP_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_UPSCALE_API_KEY="${CLIPDROP_API_KEY}"
# Audio transcription
CMS_AI_TRANSCRIBE_API_KEY="${OPENAI_API_KEY}"
For best results and all features, you need Google, OpenAI, Clipdrop, and DeepL at the moment and they are also configured by default. If you want to use a different provider or model, you can to configure them in your .env file too. Please have a look into the ./config/cms/ai.php for the used environment variables.
Note: You can also configure the base URLs for each provider using the url key in each provider configuration, e.g.:
'transcribe' => [ // Transcribe audio
'provider' => env( 'CMS_AI_TRANSCRIBE', 'openai' ),
'model' => env( 'CMS_AI_TRANSCRIBE_MODEL', 'whisper-1' ),
'api_key' => env( 'CMS_AI_TRANSCRIBE_API_KEY' ),
'url' => 'https://openai-api.compatible-provider.com'
],
Note: To protect forms like the contact form against misuse and spam, you can configure HCaptcha.
For scheduled publishing, you need to add this line to the routes/console.php class:
\Illuminate\Support\Facades\Schedule::command('cms:publish')->daily();
To clean up soft-deleted pages, elements and files regularly, add these lines to the routes/console.php class:
\Illuminate\Support\Facades\Schedule::command('model:prune', [
'--model' => [
\Aimeos\Cms\Models\Page::class,
\Aimeos\Cms\Models\Element::class,
\Aimeos\Cms\Models\File::class
],
])->daily();
Using multiple page trees with different domains is possible by adding CMS_MULTIDOMAIN=true to your .env file.
PagibleAI CMS supports single database multi-tenancy using existing Laravel tenancy packages or code implemented by your own.
The Tenancy for Laravel package is most often used. How to set up the package is described in the Multi-tenancy SaaS Setup article.
PagibleAI CMS offers tools within the Laravel MCP API that LLMs can use to interact with the CMS. Please have a look at the PagibleAI MCP documentation page for details how to set up the MCP API and Passport for authentication.
If you find a security related issue, please contact security at aimeos.org.
Contributions are welcome! Here's how you can help:
git checkout -b feature/your-feature)vendor/bin/phpunitvendor/bin/phpstan analyzegit commit -m 'Add your feature')git push origin feature/your-feature)Please make sure all tests pass and PHPStan reports no new errors before submitting.
PagibleAI CMS is licensed under the MIT.
Special thanks to:
PHP
56.9%
JavaScript
15.6%
CSS
12.0%
Vue
11.4%
Blade
4.0%
Easy, flexible and powerful cloud-native Laravel CMS package powered by AI with JSON:API, GraphQL API, templates, and themes
See the codeThe easy, flexible and scalable API-first PagibleAI CMS package for Laravel.
PagibleAI CMS is an API-first content management system that can be installed into any existing Laravel application. It combines the ease of use of WordPress with the structured content management capabilities of Contentful, powered by AI for content generation, image manipulation, and translation.
Whether you need a simple blog or a multi-tenant, multi-domain CMS serving millions of pages, PagibleAI scales to your needs — from a single SQLite-backed page to database clusters.
| Technology | Purpose |
|---|---|
| PHP 8.2+ | Backend language |
| Laravel 11.x / 12.x / 13.x | Web framework |
| Vue.js 3 | Admin panel frontend |
| Vuetify | Admin UI component library |
| Lighthouse | GraphQL API |
| Prism / Prisma PHP | AI/LLM integration |
| Vite | Frontend build tool |
PagibleAI CMS is a modular monorepo split into focused sub-packages. Each package handles a specific concern and can be used independently:
Pages are organized as a nested set tree (using _lft/_rgt columns). All content changes are tracked as immutable version snapshots — editors see the latest draft while the public sees the published version. Caching is per-page with configurable duration.
pagible/
├── src/ Meta-package (install orchestrator + serve command)
├── core/ Models, permissions, tenancy, utilities, migrations
├── admin/ Vue.js admin panel (Vuetify + Vite)
├── ai/ AI features (Prism / Prisma PHP)
├── graphql/ GraphQL API (Lighthouse)
├── backup/ Backup and restore
├── cashier/ Shared payment-backed frontend access
├── cashier-*/ Stripe, Paddle, and Mollie Cashier adapters
├── import/ CMS importers (WordPress, etc.)
├── search/ Full-text search (Laravel Scout)
├── jsonapi/ Read-only JSON:API
├── mcp/ MCP server (30+ tools)
├── theme/ Frontend rendering (Blade templates)
├── themes/ Frontend themes (CSS)
├── tests/ Shared test infrastructure
├── config/ Configuration files
└── phpunit.xml Aggregated test runner
If you don't have an existing Laravel application, create one first:
composer create-project laravel/laravel pagible
cd pagible
Then install PagibleAI CMS:
composer req aimeos/pagible
php artisan cms:install
php artisan migrate
Fresh Laravel applications contain a static public/robots.txt file. Web servers
serve that file before Laravel receives the request. If it contains custom rules,
first copy them into the robots.txt configuration element on the root page and
publish the change. Then remove the static file to enable Pagible's dynamic route:
rm public/robots.txt
The dynamic route serves the published rules together with the generated sitemap
and news sitemap URLs. Alternatively, configure the web server to pass
/robots.txt to Laravel even when the static file exists.
Now, adapt the .env file of your application and change the APP_URL setting to your domain. If you are using php artisan serve for testing, add the port of the internal web server (APP_URL=http://localhost:8000). Otherwise, the uploading files will fail because they wouldn't be loaded!
Add a line in the "post-update-cmd" section of your composer.json file to update the admin backend files after each update:
"post-update-cmd": [
"@php artisan vendor:publish --force --tag=cms-admin --tag=cms-graphql",
"@php artisan vendor:publish --tag=cms-theme",
"@php artisan migrate",
...
],
To allow users to edit CMS content or to create a new users if they don't exist yet, you can use the cms:user command (replace the e-mail address by the users one):
php artisan cms:user -e editor@example.com
This adds admin privileges for the specified user. For more information regarding authorization and permissions, please have a look into the authorization and permission page.
The CMS admin backend is available at (replace "mydomain.tld" with your own one):
http://mydomain.tld/cmsadmin
Install exactly one Pagible Cashier provider in the Laravel application that already contains Pagible CMS:
composer require aimeos/pagible-cashier-stripe
# or: aimeos/pagible-cashier-paddle
# or: aimeos/pagible-cashier-mollie
php artisan cms:install:cashier
For Stripe, an interactive installer offers to create the webhook when
APP_URL, STRIPE_KEY, and STRIPE_SECRET are ready. Automated installations
must opt in with --webhook.
Add Pagible's CashierAccess trait and the selected provider's Billable trait
to the application user model. Then configure the provider credentials and
verified webhooks, define a frontend access value such as premium-members, and
run the local readiness check:
php artisan cms:cashier:check
Use that same access value in both places in the CMS admin:
pricing element to a public sales page and select premium-members as
the package's frontend access role. Add a subscription price, a one-time
price, or both, then publish the pricing content.premium-members, and apply the change.Verified payment webhooks grant and revoke the role automatically. A successful one-time payment grants permanent access unless it is fully refunded or charged back. A subscription grants access through its provider-confirmed paid period. See the Pagible Cashier guide for the user-model example, access-catalog setup, provider-specific price fields, webhook configuration, private files, cancellations, and an end-to-end checklist.
File uploads use the Laravel disk configured by CMS_DISK and are public by default. Set
CMS_PRIVATE_DISK to a different, non-public Laravel disk to enable the translated
“Protect with page access” option in file fields. Temporary URLs generated by remote private
disks expire after CMS_PRIVATE_TTL seconds (300 by default); local private files are streamed
through the access-controlled CMS route.
To generate texts/images from prompts, analyze image/video/audio content, or execute actions based on your prompts, you have to configure one or more of the AI service providers supported by the Prism and Prisma packages.
Note: You only need to configure API keys for the AI service providers you are using, not for all!
All service providers require to sign-up and create an account first. They will provide
an API key which you need to add to your .env file or as environment variable, e.g.:
GEMINI_API_KEY="..."
OPENAI_API_KEY="..."
CLIPDROP_API_KEY="..."
DEEPL_API_KEY="..."
# Text translation
CMS_AI_TRANSLATE_API_KEY="${DEEPL_API_KEY}"
# For DeepL Pro accounts
# CMS_AI_TRANSLATE_URL="https://api.deepl.com/"
# Analyze content and generate text/images
CMS_AI_REFINE_API_KEY="${OPENAI_API_KEY}"
CMS_AI_WRITE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_DESCRIBE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_IMAGINE_API_KEY="${GEMINI_API_KEY}"
CMS_AI_INPAINT_API_KEY="${GEMINI_API_KEY}"
CMS_AI_REPAINT_API_KEY="${GEMINI_API_KEY}"
# Image manipulation
CMS_AI_ERASE_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_ISOLATE_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_UNCROP_API_KEY="${CLIPDROP_API_KEY}"
CMS_AI_UPSCALE_API_KEY="${CLIPDROP_API_KEY}"
# Audio transcription
CMS_AI_TRANSCRIBE_API_KEY="${OPENAI_API_KEY}"
For best results and all features, you need Google, OpenAI, Clipdrop, and DeepL at the moment and they are also configured by default. If you want to use a different provider or model, you can to configure them in your .env file too. Please have a look into the ./config/cms/ai.php for the used environment variables.
Note: You can also configure the base URLs for each provider using the url key in each provider configuration, e.g.:
'transcribe' => [ // Transcribe audio
'provider' => env( 'CMS_AI_TRANSCRIBE', 'openai' ),
'model' => env( 'CMS_AI_TRANSCRIBE_MODEL', 'whisper-1' ),
'api_key' => env( 'CMS_AI_TRANSCRIBE_API_KEY' ),
'url' => 'https://openai-api.compatible-provider.com'
],
Note: To protect forms like the contact form against misuse and spam, you can configure HCaptcha.
For scheduled publishing, you need to add this line to the routes/console.php class:
\Illuminate\Support\Facades\Schedule::command('cms:publish')->daily();
To clean up soft-deleted pages, elements and files regularly, add these lines to the routes/console.php class:
\Illuminate\Support\Facades\Schedule::command('model:prune', [
'--model' => [
\Aimeos\Cms\Models\Page::class,
\Aimeos\Cms\Models\Element::class,
\Aimeos\Cms\Models\File::class
],
])->daily();
Using multiple page trees with different domains is possible by adding CMS_MULTIDOMAIN=true to your .env file.
PagibleAI CMS supports single database multi-tenancy using existing Laravel tenancy packages or code implemented by your own.
The Tenancy for Laravel package is most often used. How to set up the package is described in the Multi-tenancy SaaS Setup article.
PagibleAI CMS offers tools within the Laravel MCP API that LLMs can use to interact with the CMS. Please have a look at the PagibleAI MCP documentation page for details how to set up the MCP API and Passport for authentication.
If you find a security related issue, please contact security at aimeos.org.
Contributions are welcome! Here's how you can help:
git checkout -b feature/your-feature)vendor/bin/phpunitvendor/bin/phpstan analyzegit commit -m 'Add your feature')git push origin feature/your-feature)Please make sure all tests pass and PHPStan reports no new errors before submitting.
PagibleAI CMS is licensed under the MIT.
Special thanks to:
PHP
56.9%
JavaScript
15.6%
CSS
12.0%
Vue
11.4%
Blade
4.0%