<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aimeos</title>
    <description>The latest articles on DEV Community by Aimeos (@aimeos).</description>
    <link>https://dev.to/aimeos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F203414%2Ff8316571-2fde-46f7-bc09-cc4561d38a21.png</url>
      <title>DEV Community: Aimeos</title>
      <link>https://dev.to/aimeos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aimeos"/>
    <language>en</language>
    <item>
      <title>Best AI CMS 2026: 8 compared on drafts, models and MCP</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Thu, 05 Nov 2026 16:45:11 +0000</pubDate>
      <link>https://dev.to/aimeos/best-ai-cms-2026-8-compared-on-drafts-models-and-mcp-b3n</link>
      <guid>https://dev.to/aimeos/best-ai-cms-2026-8-compared-on-drafts-models-and-mcp-b3n</guid>
      <description>&lt;p&gt;Every CMS advertises AI now. Sometimes that's a rephrase button, sometimes an agent that builds whole pages. In half of the eight CMSs I checked, AI output isn't validated against your content model at all, or only partly. And the details developers care about are usually buried in pricing tables and docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does AI output go live immediately or into a draft?&lt;/li&gt;
&lt;li&gt;Is it validated against your content model?&lt;/li&gt;
&lt;li&gt;Can you choose the model, or are you locked to the vendor's?&lt;/li&gt;
&lt;li&gt;Is AI part of the product or an Enterprise add-on?&lt;/li&gt;
&lt;li&gt;Can agents like Claude or ChatGPT work with your content via MCP?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Free AI with your own model: Drupal, PagibleAI and WordPress&lt;/li&gt;
&lt;li&gt;Hosted with the strictest guardrails: Sanity&lt;/li&gt;
&lt;li&gt;Built-in AI only on paid plans: Contentful, Payload and Strapi&lt;/li&gt;
&lt;li&gt;AI output checked against the content model: PagibleAI and Sanity, in Contentful if you turn it on&lt;/li&gt;
&lt;li&gt;MCP servers that save agent changes as drafts: Contentful, PagibleAI, Sanity and Strapi (with Draft &amp;amp; Publish)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AI feature comparison
&lt;/h2&gt;

&lt;p&gt;✅ yes · ⚠️ partly or with conditions · ❌ no · ❓ not documented or closed source&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Contentful&lt;/th&gt;
&lt;th&gt;Drupal&lt;/th&gt;
&lt;th&gt;PagibleAI&lt;/th&gt;
&lt;th&gt;Payload&lt;/th&gt;
&lt;th&gt;Sanity&lt;/th&gt;
&lt;th&gt;Storyblok&lt;/th&gt;
&lt;th&gt;Strapi&lt;/th&gt;
&lt;th&gt;WordPress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create/change pages by chat&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❓&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate text for any field&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Translate whole pages&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate images&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit images&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❓&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alt text&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❓&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI changes as drafts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❓&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI output validated&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❓&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Own model per task&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No credits or Enterprise plan&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runs on your own server&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP server&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;PagibleAI also transcribes audio and can uncrop and upscale images. Of the others, only Drupal offers transcription, as a &lt;a href="https://project.pages.drupalcode.org/ai/1.2.x/developers/call_speech_to_text/" rel="noopener noreferrer"&gt;speech-to-text API&lt;/a&gt; for developers.&lt;/p&gt;

&lt;p&gt;Statamic and Craft CMS aren't in the table because neither has first-party AI features; both rely on third-party addons. Craft 5.12 (November 2026) ships an MCP server in core, while Statamic only has community servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contentful
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.contentful.com/products/ai/ai-actions/" rel="noopener noreferrer"&gt;AI Actions&lt;/a&gt; cover translation, rewriting, alt text, SEO and custom prompts. A Content Operations Agent is in beta. You can &lt;a href="https://www.contentful.com/help/ai-automations/ai-actions/bring-your-own-model/" rel="noopener noreferrer"&gt;bring your own model&lt;/a&gt; via OpenAI, AWS Bedrock, Google Vertex AI, Azure or any OpenAI-compatible endpoint. AI Actions can't generate images; for that, Contentful offers a separate &lt;a href="https://www.contentful.com/help/apps/ai-image-generator/" rel="noopener noreferrer"&gt;AI Image Generator app&lt;/a&gt; that uses DALL-E with your own OpenAI key.&lt;/p&gt;

&lt;p&gt;Entries stay drafts until someone publishes them, and automations can check AI output against the target field's rules if you turn that on.&lt;/p&gt;

&lt;p&gt;You'll only get AI Actions as an Enterprise/Premium add-on with metered credits. The $300/month Lite plan doesn't include them, and Contentful is SaaS only.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.contentful.com/blog/remote-mcp-now-generally-available/" rel="noopener noreferrer"&gt;remote MCP server&lt;/a&gt; has been free and generally available since July 2026, and there's also a local MIT server. New entries are drafts, but agents can also publish them directly, limited by the user's permissions and an admin allow-list of tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drupal
&lt;/h2&gt;

&lt;p&gt;Drupal has the broadest AI ecosystem. The &lt;a href="https://www.drupal.org/project/ai" rel="noopener noreferrer"&gt;AI module&lt;/a&gt; bundles CKEditor AI, automators, a chatbot and observability, and supports &lt;a href="https://new.drupal.org/ai/about-drupal-ai/providers" rel="noopener noreferrer"&gt;48 AI providers&lt;/a&gt;. &lt;a href="https://www.drupal.org/blog/drupal-cms-20-is-here-visual-building-ai-and-site-templates-transform-drupal" rel="noopener noreferrer"&gt;Drupal CMS 2.0&lt;/a&gt; adds optional page generation from prompts with Canvas agents. Everything is GPL and free.&lt;/p&gt;

&lt;p&gt;No other CMS here supports more providers, and Drupal's revisions and Content Moderation apply to AI changes, too. Translations can be created as drafts.&lt;/p&gt;

&lt;p&gt;You have to combine several separate projects yourself, though. And &lt;a href="https://project.pages.drupalcode.org/canvas/ai-assistant/" rel="noopener noreferrer"&gt;Canvas' own docs&lt;/a&gt; warn that the AI can return invalid component IDs or enum values that cause render errors.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.drupal.org/project/mcp_server" rel="noopener noreferrer"&gt;MCP Server&lt;/a&gt; module is still in beta, and the Drupal AI docs advise against connecting outside agents to critical sites before a stable release.&lt;/p&gt;

&lt;h2&gt;
  
  
  PagibleAI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;PagibleAI&lt;/a&gt; is an MIT-licensed CMS package for Laravel, and its AI features are part of the open source package: a chat that creates, refines and translates pages, page-wide refine prompts, text generation for any field, queued translation of whole pages, image generation and editing (inpaint, erase, remove background, uncrop, upscale), alt text and audio transcription.&lt;/p&gt;

&lt;p&gt;Every AI change is saved as a draft version you can diff in the history. Output is checked against the JSON schema that also defines the editor form, and the same schema lets you exclude fields from translation with &lt;code&gt;"translate": false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each task can use its own provider and model from &lt;a href="https://github.com/aimeos/prisma#supported-providers" rel="noopener noreferrer"&gt;40+ providers&lt;/a&gt;, including Anthropic, OpenAI, Gemini, Mistral, Ollama and DeepL. There are no AI credits, you pay the providers directly. Switching a task to another provider takes a few lines in your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CMS_AI_WRITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;anthropic
&lt;span class="nv"&gt;CMS_AI_WRITE_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;claude-sonnet-5
&lt;span class="nv"&gt;CMS_AI_WRITE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;span class="nv"&gt;CMS_AI_TRANSLATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepl
&lt;span class="nv"&gt;CMS_AI_TRANSLATE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It requires Laravel, though. It's also the youngest CMS here, with a smaller community and no plugin marketplace yet.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://pagible.com/configure-mcp" rel="noopener noreferrer"&gt;built-in MCP server&lt;/a&gt; has 43 tools, uses OAuth via Laravel Passport and checks the user's permissions on every call. Agent changes are saved as drafts, and only users with publish rights can put them live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payload
&lt;/h2&gt;

&lt;p&gt;Payload is MIT-licensed and self-hosted, with drafts and versions in its open source core. Its first-party AI is part of &lt;a href="https://payloadcms.com/enterprise/enterprise-ai" rel="noopener noreferrer"&gt;Payload Enterprise&lt;/a&gt; and closed source: a writing assistant and auto-embedding for AI search, with AI translations and image generation marked as "coming soon".&lt;/p&gt;

&lt;p&gt;Drafts and versions work well and come with the free core.&lt;/p&gt;

&lt;p&gt;Without Enterprise, you depend on community plugins for AI. The AI code isn't public, and the docs don't say whether AI changes become drafts or are validated against your fields. Payload says the writing assistant works with "your preferred LLM", but doesn't document how you configure it.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://payloadcms.com/docs/plugins/mcp" rel="noopener noreferrer"&gt;MCP plugin&lt;/a&gt; runs on your own server and respects Payload's access control. The docs don't say whether agents can publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sanity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.sanity.io/docs/studio/ai-assist-content-translation" rel="noopener noreferrer"&gt;AI Assist&lt;/a&gt; handles field instructions, translation, image generation and alt text from the Growth plan ($15 per seat). &lt;a href="https://www.sanity.io/docs/agent-actions/introduction" rel="noopener noreferrer"&gt;Agent Actions&lt;/a&gt; (Generate, Transform, Translate, Prompt, Patch) and the chat-based &lt;a href="https://www.sanity.io/docs/content-agent/introduction" rel="noopener noreferrer"&gt;Content Agent&lt;/a&gt; are available on all plans, including Free, with 1,000 AI credits per month.&lt;/p&gt;

&lt;p&gt;Of the hosted options, Sanity keeps AI on the shortest leash. Agent Actions know your schema, and Content Agent stages edits as drafts that a person publishes.&lt;/p&gt;

&lt;p&gt;You can't bring your own model, Sanity picks it. Content lives in the proprietary Content Lake, and version history depends on the plan (3 days on Free, 90 on Growth).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.sanity.io/docs/ai/mcp-server" rel="noopener noreferrer"&gt;hosted MCP server&lt;/a&gt; works within the user's role and writes into drafts or releases, and publishing is a separate tool call. Custom validation rules in your schema don't run for MCP writes, though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storyblok
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.storyblok.com/docs/manuals/ai-assistance" rel="noopener noreferrer"&gt;AI translations, alt text, ideation and SEO&lt;/a&gt; are included on all plans, even the free Starter plan with 25k credits. &lt;a href="https://www.storyblok.com/docs/manuals/agents" rel="noopener noreferrer"&gt;Storyblok Agents&lt;/a&gt; (beta) run chat and scheduled tasks on Growth ($99/month) and up, and every write needs manual approval.&lt;/p&gt;

&lt;p&gt;Getting started costs nothing, and a person has to approve every agent change.&lt;/p&gt;

&lt;p&gt;There's no image generation. Your own AI provider is limited to the top tiers, and version history covers 1 day on Starter and 30 days on Growth. Validation is partial: the Management API checks maximum lengths and block counts, but regex patterns only apply in the Visual Editor.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.storyblok.com/lp/mcp-server" rel="noopener noreferrer"&gt;hosted MCP server&lt;/a&gt; has 155+ tools in read-only, mutating and destructive modes, and can publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strapi
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.strapi.io/cms/ai/for-content-managers" rel="noopener noreferrer"&gt;Strapi AI&lt;/a&gt; offers a chat assistant in the Content-Type Builder, AI translations and AI metadata (alt text, captions). It needs the Growth license ($45/month for 3 users) with 1,000 credits per month.&lt;/p&gt;

&lt;p&gt;The Content-Type Builder assistant helps you design content models, which none of the others offer.&lt;/p&gt;

&lt;p&gt;There's no writing assistant for content and no image generation. The Community edition has neither AI nor content history, and your own model requires Enterprise. If Draft &amp;amp; Publish is off, AI translations go live right away and overwrite manual edits in the target locale.&lt;/p&gt;

&lt;p&gt;Strapi 5.49 made its &lt;a href="https://strapi.io/blog/the-strapi-mcp-server-is-now-ga" rel="noopener noreferrer"&gt;built-in MCP server&lt;/a&gt; generally available on all plans. It's off by default and runs inside your instance. With Draft &amp;amp; Publish enabled, new entries land as drafts, and agents can publish them within the token owner's permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress
&lt;/h2&gt;

&lt;p&gt;The official &lt;a href="https://make.wordpress.org/ai/2026/05/21/whats-new-in-ai-1-0-0/" rel="noopener noreferrer"&gt;AI plugin&lt;/a&gt; (formerly "AI Experiments") reached 1.0 in May 2026. It's free and has 18 opt-in features: titles, excerpts, summaries, rephrasing, meta descriptions, alt text, image generation and editing, tag suggestions, comment moderation and more.&lt;/p&gt;

&lt;p&gt;You choose the provider per feature (Claude, Gemini, OpenAI and others via provider plugins). Most features produce suggestions that a person applies, so AI doesn't change content behind your back.&lt;/p&gt;

&lt;p&gt;The features work on single fields and posts, not whole sites. Translation isn't part of the plugin; &lt;a href="https://jetpack.com/ai/" rel="noopener noreferrer"&gt;Jetpack AI&lt;/a&gt; offers it with a small free quota and paid plans. Generated texts aren't validated against blocks, and generated images go straight into the Media Library.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://wordpress.org/plugins/mcp-adapter/" rel="noopener noreferrer"&gt;MCP Adapter&lt;/a&gt; plugin only exposes read-only abilities by default, so what agents can do depends on what your plugins register. WordPress.com has a &lt;a href="https://wordpress.com/support/mcp/" rel="noopener noreferrer"&gt;hosted MCP server&lt;/a&gt; that can write and publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one should you use?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you're on WordPress, check whether the free AI plugin is enough. If it isn't, look at Drupal and PagibleAI.&lt;/li&gt;
&lt;li&gt;If you want a hosted CMS, Sanity has the strictest guardrails, but you can't choose the model. Contentful sells AI Actions as an Enterprise add-on.&lt;/li&gt;
&lt;li&gt;If you want to pick your models freely, Drupal and PagibleAI support the most providers.&lt;/li&gt;
&lt;li&gt;If you work with Node.js, Strapi and Payload include MCP for free, but built-in AI needs Strapi Growth or Payload Enterprise.&lt;/li&gt;
&lt;li&gt;If you work with Laravel, PagibleAI gives you all AI features for free.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I compared
&lt;/h2&gt;

&lt;p&gt;I went through the official docs, changelogs and pricing pages of eight CMSs in November 2026. For WordPress, Strapi and PagibleAI, I also checked draft handling and validation in their source code. Drupal's Canvas docs already state that AI output isn't validated, so I skipped the source check there. Payload's AI is closed source, so its cells stay open. I didn't run paid Enterprise trials, and features only documented behind sales calls are marked as such.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Last updated: November 5, 2026&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Contentful: &lt;a href="https://www.contentful.com/pricing/" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;, &lt;a href="https://www.contentful.com/help/ai-automations/ai-actions/" rel="noopener noreferrer"&gt;AI Actions&lt;/a&gt;, &lt;a href="https://www.contentful.com/help/ai-automations/ai-actions/bring-your-own-model/" rel="noopener noreferrer"&gt;bring your own model&lt;/a&gt;, &lt;a href="https://www.contentful.com/help/apps/ai-image-generator/" rel="noopener noreferrer"&gt;AI Image Generator&lt;/a&gt;, &lt;a href="https://www.contentful.com/blog/remote-mcp-now-generally-available/" rel="noopener noreferrer"&gt;remote MCP&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Craft CMS: &lt;a href="https://craftcms.com/docs/5.x/system/mcp" rel="noopener noreferrer"&gt;MCP in 5.12&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Drupal: &lt;a href="https://www.drupal.org/project/ai" rel="noopener noreferrer"&gt;AI module&lt;/a&gt;, &lt;a href="https://new.drupal.org/ai/about-drupal-ai/providers" rel="noopener noreferrer"&gt;providers&lt;/a&gt;, &lt;a href="https://project.pages.drupalcode.org/ai/1.2.x/developers/call_speech_to_text/" rel="noopener noreferrer"&gt;speech-to-text&lt;/a&gt;, &lt;a href="https://www.drupal.org/project/ai_translate" rel="noopener noreferrer"&gt;AI Translate&lt;/a&gt;, &lt;a href="https://www.drupal.org/blog/drupal-cms-20-is-here-visual-building-ai-and-site-templates-transform-drupal" rel="noopener noreferrer"&gt;Drupal CMS 2.0&lt;/a&gt;, &lt;a href="https://project.pages.drupalcode.org/canvas/ai-assistant/" rel="noopener noreferrer"&gt;Canvas AI&lt;/a&gt;, &lt;a href="https://www.drupal.org/project/mcp_server" rel="noopener noreferrer"&gt;MCP Server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PagibleAI: &lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;pagible.com&lt;/a&gt;, &lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://github.com/aimeos/prisma#supported-providers" rel="noopener noreferrer"&gt;Prisma providers&lt;/a&gt;, &lt;a href="https://pagible.com/configure-mcp" rel="noopener noreferrer"&gt;MCP setup&lt;/a&gt;, &lt;a href="https://github.com/aimeos/pagible/blob/master/core/src/JsonSchema.php" rel="noopener noreferrer"&gt;JsonSchema.php&lt;/a&gt;, &lt;a href="https://github.com/aimeos/pagible/blob/master/ai/src/Ai.php" rel="noopener noreferrer"&gt;Ai.php&lt;/a&gt;, &lt;a href="https://github.com/aimeos/pagible/blob/master/core/src/Resource/Variants.php" rel="noopener noreferrer"&gt;Variants.php&lt;/a&gt;, &lt;a href="https://github.com/aimeos/pagible/blob/master/ai/src/GraphQL/Mutations/Imagine.php" rel="noopener noreferrer"&gt;Imagine.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Payload: &lt;a href="https://payloadcms.com/enterprise/enterprise-ai" rel="noopener noreferrer"&gt;Enterprise AI&lt;/a&gt;, &lt;a href="https://payloadcms.com/enterprise/ai-framework" rel="noopener noreferrer"&gt;AI framework&lt;/a&gt;, &lt;a href="https://payloadcms.com/docs/plugins/mcp" rel="noopener noreferrer"&gt;MCP plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sanity: &lt;a href="https://www.sanity.io/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;, &lt;a href="https://www.sanity.io/docs/agent-actions/introduction" rel="noopener noreferrer"&gt;Agent Actions&lt;/a&gt;, &lt;a href="https://www.sanity.io/docs/content-agent/introduction" rel="noopener noreferrer"&gt;Content Agent&lt;/a&gt;, &lt;a href="https://www.sanity.io/docs/ai/mcp-server" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Storyblok: &lt;a href="https://www.storyblok.com/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;, &lt;a href="https://www.storyblok.com/docs/manuals/ai-assistance" rel="noopener noreferrer"&gt;AI assistance&lt;/a&gt;, &lt;a href="https://www.storyblok.com/docs/manuals/agents" rel="noopener noreferrer"&gt;Agents&lt;/a&gt;, &lt;a href="https://www.storyblok.com/lp/mcp-server" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt;, &lt;a href="https://www.storyblok.com/cl/we-re-enforcing-field-validation-rules-on-the-management-api" rel="noopener noreferrer"&gt;API validation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Strapi: &lt;a href="https://docs.strapi.io/cms/ai/for-content-managers" rel="noopener noreferrer"&gt;AI&lt;/a&gt;, &lt;a href="https://strapi.io/pricing-self-hosted" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;, &lt;a href="https://strapi.io/blog/the-strapi-mcp-server-is-now-ga" rel="noopener noreferrer"&gt;MCP server&lt;/a&gt;, &lt;a href="https://docs.strapi.io/cms/features/strapi-mcp-server" rel="noopener noreferrer"&gt;MCP docs&lt;/a&gt;, &lt;a href="https://github.com/strapi/strapi/blob/develop/packages/plugins/i18n/server/src/services/ai-localizations.ts" rel="noopener noreferrer"&gt;ai-localizations.ts&lt;/a&gt;, &lt;a href="https://github.com/strapi/strapi/blob/develop/packages/core/core/src/services/entity-validator/validators.ts" rel="noopener noreferrer"&gt;validators.ts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;WordPress: &lt;a href="https://make.wordpress.org/ai/2026/05/21/whats-new-in-ai-1-0-0/" rel="noopener noreferrer"&gt;AI plugin 1.0&lt;/a&gt;, &lt;a href="https://jetpack.com/ai/" rel="noopener noreferrer"&gt;Jetpack AI&lt;/a&gt;, &lt;a href="https://developer.wordpress.org/news/2026/02/from-abilities-to-ai-agents-introducing-the-wordpress-mcp-adapter/" rel="noopener noreferrer"&gt;MCP Adapter&lt;/a&gt;, &lt;a href="https://wordpress.com/support/mcp/" rel="noopener noreferrer"&gt;WordPress.com MCP&lt;/a&gt;, &lt;a href="https://github.com/WordPress/ai/blob/develop/includes/Abilities/Title_Generation/Title_Generation.php" rel="noopener noreferrer"&gt;Title_Generation.php&lt;/a&gt;, &lt;a href="https://github.com/WordPress/ai/blob/develop/includes/Abilities/Image/Import_Base64_Image.php" rel="noopener noreferrer"&gt;Import_Base64_Image.php&lt;/a&gt;, &lt;a href="https://github.com/WordPress/ai/blob/develop/src/experiments/alt-text-generation/bulk.ts" rel="noopener noreferrer"&gt;bulk.ts&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which AI features do you actually use in your CMS, and which ones did you turn off again? I'm curious what works in real projects.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>cms</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Aimeos 2026.10: MCP tools for Laravel e-commerce</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Tue, 27 Oct 2026 13:03:34 +0000</pubDate>
      <link>https://dev.to/aimeos/aimeos-202610-mcp-tools-for-laravel-e-commerce-49lc</link>
      <guid>https://dev.to/aimeos/aimeos-202610-mcp-tools-for-laravel-e-commerce-49lc</guid>
      <description>&lt;p&gt;Aimeos is an open-source e-commerce framework for Laravel applications. Version 2026.10 adds MCP tools that let AI agents search products, update orders and manage customers in your shop.&lt;/p&gt;

&lt;p&gt;An agent could retrieve selected products, draft improved descriptions and save the changes after your approval. Aimeos provides the tools for reading and updating shop data; your integration handles the agent workflow and approval step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MCP tools for AI agents
&lt;/h3&gt;

&lt;p&gt;Model Context Protocol (MCP) gives AI applications a standard way to discover and call tools. The new &lt;code&gt;ai-admin-mcp&lt;/code&gt; extension provides tools for more than 20 shop domains, including products, categories, orders, customers and stock. Depending on the domain, agents can search and aggregate records, save and delete items, and change category trees.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/ai-admin-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each tool validates its arguments and checks permissions using the Aimeos context supplied by your integration. In &lt;code&gt;admin/mcp/resource&lt;/code&gt; you configure which user groups may call which tool.&lt;/p&gt;

&lt;p&gt;The package doesn't include an MCP transport or SDK. Each tool exposes an input schema and returns its results as PHP arrays.&lt;/p&gt;

&lt;p&gt;Your integration registers the tool definitions with an MCP server and routes calls to their execution methods. Expose only the tools you need. The &lt;a href="https://github.com/aimeos/ai-admin-mcp#readme" rel="noopener noreferrer"&gt;MCP package README&lt;/a&gt; shows how to retrieve the tool catalog, inspect definitions and execute calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebMCP in the storefront
&lt;/h3&gt;

&lt;p&gt;WebMCP is a proposed browser standard that lets websites describe actions for AI agents. The Aimeos storefront now uses it on the forms for addresses, saved baskets, coupons and product watch lists. Browser agents that support WebMCP can fill these forms for the customer. Few browsers support it yet, and for regular visitors the forms work as before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose an AI provider for each task
&lt;/h3&gt;

&lt;p&gt;In the admin backend, you can write and translate texts, generate images and remove image backgrounds with AI. In 2026.10, these features use &lt;a href="https://github.com/aimeos/prisma#readme" rel="noopener noreferrer"&gt;Prisma (&lt;code&gt;aimeos/prisma&lt;/code&gt;)&lt;/a&gt;, our PHP library for AI providers. You can configure a different provider and model for each task. Switching providers later is a configuration change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Imports and exports
&lt;/h3&gt;

&lt;p&gt;Customer, product, category and supplier imports can combine file data with configured values. For example, set a fixed &lt;code&gt;product.status&lt;/code&gt; in the import mapping and omit the repetitive status column from your CSV.&lt;/p&gt;

&lt;p&gt;Order, product and subscription exports can be extended with project-specific data before the files are written, for example fields your ERP or CRM system expects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework support
&lt;/h3&gt;

&lt;p&gt;Laravel 10 to 13 remain supported, Symfony 8 and TYPO3 14 are now supported too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security hardening
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customer password hashes are excluded from loaded customer items and API responses. Admin APIs apply tighter checks to shared items and customer group assignments.&lt;/li&gt;
&lt;li&gt;HTML sanitization and output encoding strengthen XSS protection. Remote image and CMS media fetching blocks internal addresses to protect against SSRF.&lt;/li&gt;
&lt;li&gt;Checkout steps require POST requests. Guest orders can't be linked to existing accounts by e-mail, and site settings can't overwrite internal configuration keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For published vulnerabilities and affected versions, see the &lt;a href="https://github.com/aimeos/aimeos-core/security/advisories" rel="noopener noreferrer"&gt;core security advisories&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Aimeos fits into your application
&lt;/h2&gt;

&lt;p&gt;You can install Aimeos (LGPLv3) into an existing Laravel application as a Composer package. It uses your routes, middleware, authentication, queues and Blade views.&lt;/p&gt;

&lt;p&gt;Use the JSON:API for a custom frontend, or start with the server-rendered HTML components included with Aimeos. GraphQL and now MCP cover administration.&lt;/p&gt;

&lt;p&gt;Aimeos is multi-vendor, multi-language, and multi-currency capable so you can run several shops with their own catalogs, prices, languages and currencies.&lt;/p&gt;

&lt;p&gt;Aimeos is self-hosted, so you control your shop database and hosting, with no Aimeos fees per transaction. Data sent to external AI services depends on the provider and features you configure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;You can install different packages, depending on your needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Full shop system&lt;/span&gt;
composer create-project aimeos/aimeos

&lt;span class="c"&gt;# Headless API&lt;/span&gt;
composer create-project aimeos/aimeos-headless

&lt;span class="c"&gt;# Laravel package only&lt;/span&gt;
composer require aimeos/aimeos-laravel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New to Aimeos?&lt;/strong&gt; Follow the &lt;a href="https://aimeos.org/docs/latest/laravel/setup/" rel="noopener noreferrer"&gt;Laravel setup guide&lt;/a&gt; or explore the &lt;a href="https://demo.aimeos.org" rel="noopener noreferrer"&gt;demo shop&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upgrading an existing shop?&lt;/strong&gt; Read the &lt;a href="https://aimeos.org/docs/latest/laravel/setup/#upgrade" rel="noopener noreferrer"&gt;upgrade guidance&lt;/a&gt; before updating your dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building an agent integration?&lt;/strong&gt; Install &lt;code&gt;aimeos/ai-admin-mcp&lt;/code&gt; and use the &lt;a href="https://github.com/aimeos/ai-admin-mcp#readme" rel="noopener noreferrer"&gt;tool catalog example&lt;/a&gt; to connect the tools to your MCP server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the application source on &lt;a href="https://github.com/aimeos/aimeos" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you like Aimeos, give it a star! :-)&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>PagibleAI CMS 0.13: Review with AI, publish with confidence</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Mon, 19 Oct 2026 09:11:04 +0000</pubDate>
      <link>https://dev.to/aimeos/pagibleai-cms-013-review-with-ai-publish-with-confidence-12c3</link>
      <guid>https://dev.to/aimeos/pagibleai-cms-013-review-with-ai-publish-with-confidence-12c3</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;PagibleAI&lt;/a&gt; is an MIT-licensed CMS for Laravel with visual editing, versioned content, and APIs for headless frontends and AI agents. It runs on PHP 8.2+ with Laravel 11, 12 or 13.&lt;/p&gt;

&lt;p&gt;PagibleAI 0.13 helps you review content before publishing and keep connected systems updated afterwards. Ask the AI assistant to check a page, inspect its changes in the history, and publish when you're ready. Optional webhook and CDN packages notify your integrations and purge affected URLs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8nt44z8ga9fnfr2141h5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8nt44z8ga9fnfr2141h5.gif" alt=" " width="600" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Review a page before publishing
&lt;/h2&gt;

&lt;p&gt;Version 0.13 teaches the AI assistant built-in SEO rules for page reviews. Just click on the magic AI button and the assistant checks heading structure, meta description, canonical and robots settings, broken links and more. It explains what it found and you can then ask it in the chat to apply all suggestions or parts of it to the draft before you publish.&lt;/p&gt;

&lt;p&gt;Before publishing, open the redesigned history dialog. Large text diffs collapse to the changed passages, and unpublished versions are marked clearly, so you see exactly what the AI and your colleagues changed.&lt;/p&gt;

&lt;p&gt;To enable the chat, set its provider and API key with &lt;code&gt;CMS_AI_WRITE&lt;/code&gt; and &lt;code&gt;CMS_AI_WRITE_API_KEY&lt;/code&gt;, as described in the &lt;a href="https://github.com/aimeos/pagible#configuration" rel="noopener noreferrer"&gt;AI configuration guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit without losing your place
&lt;/h2&gt;

&lt;p&gt;Visual editing now opens content fields in a sidebar next to the preview. Change a headline while its layout stays visible, then check desktop, tablet and phone sizes. The element picker adds search, group tabs and descriptions.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;Ctrl/Cmd+K&lt;/code&gt; to jump to a page, element, file or action with the new command palette. &lt;code&gt;Ctrl/Cmd+S&lt;/code&gt; saves; &lt;code&gt;Ctrl/Cmd+Shift+S&lt;/code&gt; opens the publishing menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trigger integrations with signed webhooks
&lt;/h2&gt;

&lt;p&gt;Publishing often starts another task: updating a search service, rebuilding a static frontend, or sending content to another channel.&lt;/p&gt;

&lt;p&gt;The optional &lt;a href="https://github.com/aimeos/pagible/blob/master/webhooks/README.md" rel="noopener noreferrer"&gt;&lt;code&gt;aimeos/pagible-webhooks&lt;/code&gt; package&lt;/a&gt; sends tenant-scoped notifications through Laravel's queue when pages, elements or files are published, deleted, restored or purged, and when pages are moved (&lt;code&gt;page.published&lt;/code&gt;, &lt;code&gt;element.deleted&lt;/code&gt;, &lt;code&gt;file.purged&lt;/code&gt; and so on).&lt;/p&gt;

&lt;p&gt;Each notification identifies what changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"page.published"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tenant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tenant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-14T12:00:00.000+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"01995d6a-cb84-7218-9bb9-79063c4bf681"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"01995d6a-cb84-7218-9bb9-79063c4bf682"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"products/example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requests use Standard Webhooks signatures. The &lt;a href="https://github.com/aimeos/pagible/blob/master/webhooks/README.md#verifying-requests" rel="noopener noreferrer"&gt;webhook verification guide&lt;/a&gt; provides a complete Laravel receiver covering signature and timestamp checks, duplicate deliveries and queued processing. For a search integration, your job fetches the current content to update the external index, or removes an entry when content is deleted.&lt;/p&gt;

&lt;p&gt;Manage and test subscriptions in the admin panel. Temporary failures trigger retries with increasing backoff, while terminal responses such as 404 stop delivery.&lt;/p&gt;

&lt;p&gt;Run this check during deployment to validate endpoint settings, deny-list entries, queue timing and cache configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan cms:webhooks:check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command also warns about subscription secrets that can no longer be decrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Purge CDN caches when content changes
&lt;/h2&gt;

&lt;p&gt;When you correct a price or headline, your CDN needs to stop serving the old copy.&lt;/p&gt;

&lt;p&gt;The optional &lt;a href="https://github.com/aimeos/pagible/blob/master/cdn/README.md" rel="noopener noreferrer"&gt;&lt;code&gt;aimeos/pagible-cdn&lt;/code&gt; package&lt;/a&gt; purges Cloudflare, Fastly and Varnish automatically.&lt;/p&gt;

&lt;p&gt;With your provider configured and queue workers running, the package purges affected page URLs and public files removed from storage through queued jobs. Publishing a URL change queues purges for both the old and new address.&lt;/p&gt;

&lt;p&gt;For Cloudflare, configure your token and zone, then choose how long public pages may stay cached:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CMS_CDN_CLOUDFLARE_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;span class="nv"&gt;CMS_CDN_CLOUDFLARE_ZONE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;span class="nv"&gt;CMS_CDN_MAXAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;86400
&lt;span class="nv"&gt;CMS_CDN_STALE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CMS_CDN_MAXAGE=86400&lt;/code&gt; lets the CDN cache public pages for a day. &lt;code&gt;CMS_CDN_STALE=60&lt;/code&gt; allows a stale copy for up to a minute while refreshing it or if your server is unavailable.&lt;/p&gt;

&lt;p&gt;Pages that only show a changed navigation entry stay cached until they expire, so pick a lifetime your site can live with.&lt;/p&gt;

&lt;p&gt;PagibleAI also caches complete public pages in Laravel's cache, a separate layer from the CDN. The admin panel's "Clear cache" action clears a page and its subpages from the application cache and, with the CDN package configured, queues their CDN purges too. After a theme change, you can purge all CDN content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan cms:cdn:purge &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Catch content errors before submitting updates
&lt;/h2&gt;

&lt;p&gt;The new &lt;a href="https://github.com/aimeos/pagible/blob/master/jsonapi/README.md" rel="noopener noreferrer"&gt;content schema endpoint&lt;/a&gt; in 0.13 lets your frontend, form builder or AI agent read registered content, metadata and configuration definitions, including those added by themes and extensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /cms/schema
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint returns a JSON Schema Draft 2020-12 document. This excerpt shows the required &lt;code&gt;title&lt;/code&gt; field inside a hero element's &lt;code&gt;data&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"minLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A missing &lt;code&gt;title&lt;/code&gt; or an empty string fails validation before your integration submits the update.&lt;/p&gt;

&lt;p&gt;Use a Draft 2020-12 validator to check the full &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;meta&lt;/code&gt; and &lt;code&gt;config&lt;/code&gt; object, or select an individual element definition. Write changes through GraphQL or MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import content from TYPO3 and WordPress
&lt;/h2&gt;

&lt;p&gt;A new TYPO3 importer brings pages, content and files over to Laravel, preserving the page tree.&lt;/p&gt;

&lt;p&gt;Re-importing the same domain and post slug with the WordPress importer now updates and republishes the existing article instead of creating a duplicate. Each run publishes the imported changes and preserves publication dates and cover images.&lt;/p&gt;

&lt;p&gt;Both importers are available through the optional &lt;code&gt;aimeos/pagible-import&lt;/code&gt; package. They read directly from the source database, configured as a Laravel database connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan cms:t3-import &lt;span class="nt"&gt;--connection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;typo3 &lt;span class="nt"&gt;--file-base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://example.com/fileadmin
php artisan cms:wp-import &lt;span class="nt"&gt;--connection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wordpress &lt;span class="nt"&gt;--domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More in this release
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI agents:&lt;/strong&gt; Claude Code, Cursor and other MCP clients can manage pages through the built-in MCP server. Its tools now accept base64 file uploads, so your agent can attach a file without hosting it at a public URL first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Themes:&lt;/strong&gt; Taste and News add layouts for restaurants and publishers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content elements:&lt;/strong&gt; New maps, call-to-action blocks and configurable contact forms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images:&lt;/strong&gt; Smaller preview images for mobile devices, and &lt;code&gt;php artisan cms:previews&lt;/code&gt; regenerates previews for existing images.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install or upgrade
&lt;/h2&gt;

&lt;p&gt;Add the CMS to your Laravel application with the &lt;a href="https://pagible.com/install-pagibleai-cms" rel="noopener noreferrer"&gt;PagibleAI installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Already using PagibleAI? Review the &lt;a href="https://pagible.com/upgrade-pagibleai-cms" rel="noopener noreferrer"&gt;PagibleAI upgrade guide&lt;/a&gt; before updating your application.&lt;/p&gt;

&lt;p&gt;The webhooks and CDN integrations are separate packages you add when you need them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/pagible-webhooks aimeos/pagible-cdn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an editor publishes a change, which systems does your application need to update?&lt;/p&gt;

&lt;p&gt;If you like PagibleAI CMS, give it a star :-)&lt;/p&gt;

</description>
      <category>ai</category>
      <category>laravel</category>
      <category>opensource</category>
      <category>php</category>
    </item>
    <item>
      <title>The Best Laravel CMS: PagibleAI vs Statamic vs October CMS</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Fri, 31 Jul 2026 12:37:43 +0000</pubDate>
      <link>https://dev.to/aimeos/the-best-laravel-cms-pagibleai-vs-statamic-vs-october-cms-2c58</link>
      <guid>https://dev.to/aimeos/the-best-laravel-cms-pagibleai-vs-statamic-vs-october-cms-2c58</guid>
      <description>&lt;p&gt;Using Laravel internally does not make a CMS a natural fit for every Laravel application. The integration model matters more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pagible.com/laravel-cms" rel="noopener noreferrer"&gt;PagibleAI&lt;/a&gt;, &lt;a href="https://statamic.com/features" rel="noopener noreferrer"&gt;Statamic&lt;/a&gt; and &lt;a href="https://octobercms.com/features" rel="noopener noreferrer"&gt;October CMS&lt;/a&gt; all use Laravel, but they ask developers to work in different ways.&lt;/p&gt;

&lt;p&gt;Statamic is a content-first CMS centered on flat-file and Git workflows. October CMS is a website platform built around Twig, themes and plugins. PagibleAI is a modular CMS package designed to live inside an existing Laravel application.&lt;/p&gt;

&lt;p&gt;For a content-led marketing site, that difference may be small. For a SaaS product, customer portal, marketplace or multi-tenant application, it can determine whether the CMS simplifies the architecture or becomes another architecture beside it.&lt;/p&gt;

&lt;p&gt;For projects where Laravel is the product rather than an implementation detail, PagibleAI is often the most direct fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;PagibleAI&lt;/th&gt;
&lt;th&gt;Statamic&lt;/th&gt;
&lt;th&gt;October CMS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product shape&lt;/td&gt;
&lt;td&gt;Composer package inside a Laravel app&lt;/td&gt;
&lt;td&gt;Full Laravel CMS, installable standalone or into Laravel&lt;/td&gt;
&lt;td&gt;Full CMS platform built on Laravel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default content model&lt;/td&gt;
&lt;td&gt;Database-backed Eloquent models&lt;/td&gt;
&lt;td&gt;Flat files, with database options available&lt;/td&gt;
&lt;td&gt;Database-backed Tailor records and plugin models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend choices&lt;/td&gt;
&lt;td&gt;Blade themes or read-only JSON:API&lt;/td&gt;
&lt;td&gt;Antlers/Blade or paid Pro REST and GraphQL APIs&lt;/td&gt;
&lt;td&gt;Twig themes; custom APIs through CMS pages or PHP routes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publishing&lt;/td&gt;
&lt;td&gt;Drafts, immutable versions, history and scheduling&lt;/td&gt;
&lt;td&gt;Revisions, drafts and history in paid Pro&lt;/td&gt;
&lt;td&gt;Tailor entries support drafts; wider workflows are project-specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;Built-in editorial AI and 33 MCP tools&lt;/td&gt;
&lt;td&gt;Addons and custom Laravel integrations&lt;/td&gt;
&lt;td&gt;Plugins plus AI-oriented developer tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Licensing&lt;/td&gt;
&lt;td&gt;MIT, no per-site fee&lt;/td&gt;
&lt;td&gt;Free Core; paid Pro required for teams, revisions, multisite and headless&lt;/td&gt;
&lt;td&gt;A production license is required; one complimentary license is available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Laravel products that need an integrated CMS&lt;/td&gt;
&lt;td&gt;Content-centric sites and Git-first teams&lt;/td&gt;
&lt;td&gt;Theme- and plugin-driven website development&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The relevant question is how closely those defaults match the application you intend to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the CMS to a Laravel application
&lt;/h2&gt;

&lt;p&gt;PagibleAI installs with Composer and two Artisan commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/pagible
php artisan cms:install
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses the Laravel application you already have: its service container, database connections, Eloquent models, authentication, middleware, cache, filesystem and deployment process. The CMS does not require a separate content service or a parallel user system.&lt;/p&gt;

&lt;p&gt;Its core records, including pages, reusable elements, files and versions, are normal Eloquent models. CMS content can therefore participate in the rest of the product.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;Page&lt;/code&gt; is an Eloquent model, a controller can retrieve CMS content with ordinary Laravel code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Cms\Models\Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'account/help'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;firstOrFail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'account.help'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'page'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model's global scope selects the active tenant, while &lt;code&gt;access()&lt;/code&gt; applies the visitor's page-access rules. Product plans, middleware and application events can interact with the same model. There is no client SDK or synchronization layer between the CMS and the application.&lt;/p&gt;

&lt;p&gt;Statamic can also be &lt;a href="https://statamic.dev/installing/laravel" rel="noopener noreferrer"&gt;installed into an existing Laravel application&lt;/a&gt;. Its documentation explains that the package installation begins without the content and views supplied by a standard Statamic site, and that content remains flat-file by default. That works when content belongs in Git. It is less natural when content belongs to database-backed product workflows.&lt;/p&gt;

&lt;p&gt;October CMS takes a different approach. Its plugin system introduces October-specific conventions: plugin registration files, CMS components, backend controllers, Twig themes and its own extension lifecycle. The team is building an October application powered by Laravel, rather than adding a CMS-shaped module to an otherwise conventional Laravel product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content storage and versions
&lt;/h2&gt;

&lt;p&gt;Statamic's flat-file model puts content and configuration in Git, where they can be reviewed in pull requests and deployed with code. That workflow suits documentation sites and developer-led publications.&lt;/p&gt;

&lt;p&gt;That model is a less direct fit when editors publish continuously, many tenants share an installation, or content is related to application data.&lt;/p&gt;

&lt;p&gt;PagibleAI stores structured content in the database and gives every CMS model a tenant boundary. Editors work on the latest version while visitors receive the published version. Each save creates an immutable snapshot, making comparison, restoration and scheduling parts of the same data model.&lt;/p&gt;

&lt;p&gt;The database-first design supports SQLite, MySQL, MariaDB, PostgreSQL and SQL Server. PagibleAI's Laravel Scout integration uses each database's full-text search facility, so a project can begin without a separate search service.&lt;/p&gt;

&lt;p&gt;October CMS also uses database content. Its &lt;a href="https://docs.octobercms.com/4.x/cms/tailor/introduction.html" rel="noopener noreferrer"&gt;Tailor&lt;/a&gt; feature turns YAML blueprints into backend forms and database tables, and its plugin models are based on Eloquent. October fits projects where those blueprints, backend screens and website components define the application. PagibleAI fits cases where CMS content must coexist with an application whose domain model already exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editorial and public APIs
&lt;/h2&gt;

&lt;p&gt;PagibleAI separates editorial operations from public delivery.&lt;/p&gt;

&lt;p&gt;Its Lighthouse-based GraphQL API serves the Vue administration interface and custom management tools. Its public JSON:API is read-only and returns published content to SPAs, mobile apps, static-site generators or other services. Blade remains available when server-rendered pages are the simpler answer.&lt;/p&gt;

&lt;p&gt;A public frontend does not need administrative mutations, while an editorial client is not constrained by an API designed for anonymous traffic. Both APIs use the same content, permissions and publication state.&lt;/p&gt;

&lt;p&gt;Statamic provides REST and GraphQL APIs, but they are &lt;a href="https://statamic.dev/frontend/rest-api" rel="noopener noreferrer"&gt;Statamic Pro features&lt;/a&gt;. As of July 2026, Statamic lists Pro at &lt;a href="https://statamic.com/pricing" rel="noopener noreferrer"&gt;$349 per site, including one year of updates&lt;/a&gt;, with subsequent updates priced separately. The license also covers its control panel, developer support and additional Pro features. Headless delivery, multiple editors, revisions and multisite support therefore belong to the commercial decision.&lt;/p&gt;

&lt;p&gt;October CMS documents how to &lt;a href="https://docs.octobercms.com/4.x/cms/resources/building-apis.html" rel="noopener noreferrer"&gt;build API endpoints&lt;/a&gt; with CMS pages or PHP routes. This leaves more of the public content contract to the project. PagibleAI provides a standardized, read-only content API from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI and MCP permissions
&lt;/h2&gt;

&lt;p&gt;AI-assisted editing is useful only when generated changes follow the same permissions, tenant boundaries and publication rules as changes made by an editor.&lt;/p&gt;

&lt;p&gt;PagibleAI includes tools for drafting and refining text, generating and editing images, transcription, translation and SEO assistance. These features are optional: the CMS works without configuring a model provider.&lt;/p&gt;

&lt;p&gt;PagibleAI also exposes &lt;a href="https://pagible.com/configure-mcp" rel="noopener noreferrer"&gt;33 content-management tools through MCP&lt;/a&gt;. An authorized assistant can search pages, inspect the page tree, create a draft, update reusable elements, manage media, translate content and schedule publication.&lt;/p&gt;

&lt;p&gt;Each MCP operation uses the authenticated user's permissions and tenant. Changes create drafts, publication remains explicit and version history provides recovery. The MCP client uses the existing publishing system rather than writing around it.&lt;/p&gt;

&lt;p&gt;Statamic and October CMS can both be connected to AI services through addons or custom Laravel code. October 4.3 also introduced AI-oriented development tooling. The difference is that editorial AI and assistant-driven CMS operations are part of PagibleAI's core product design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;PagibleAI follows Laravel's contracts for storage, caching, queues and broadcasting. A local installation can use SQLite and local files; production can move media to object storage, locks and caching to Redis, and jobs to dedicated workers without changing the content model.&lt;/p&gt;

&lt;p&gt;Existing Laravel monitoring, backups and deployment practices still apply. PagibleAI also supports Octane workers, tenant-scoped content, multiple page trees and domains, endpoint rate limits and content sanitization. These features become relevant as an installation grows beyond one site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Statamic and October CMS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Statamic: Git-centered content with Pro licensing
&lt;/h3&gt;

&lt;p&gt;Statamic combines flat-file content, a control panel, configurable field types, live preview and Git automation. This suits documentation, publications and marketing sites where developers review content in Git. Pro editon adds developer support and access to its addon ecosystem.&lt;/p&gt;

&lt;p&gt;The flat-file default fits database-backed, multi-tenant products less naturally, and installation inside an existing Laravel app needs extra setup. Multiple users, roles, revisions, multilingual and multisite support, REST and GraphQL require the &lt;a href="https://statamic.com/pricing" rel="noopener noreferrer"&gt;$349-per-site Pro edition&lt;/a&gt;. That adds cost when the application only needs an integrated CMS module.&lt;/p&gt;

&lt;h3&gt;
  
  
  October CMS: a site platform with its own conventions
&lt;/h3&gt;

&lt;p&gt;October CMS combines Twig themes, CMS components, Tailor blueprints and a plugin marketplace. It supports structured content, custom backend screens and Eloquent-based models for custom PHP. Its production license includes platform support.&lt;/p&gt;

&lt;p&gt;Adopting October means adopting its plugin lifecycle, backend controllers and Twig conventions. Public API endpoints are project code rather than a standardized content-delivery API. Each website needs a &lt;a href="https://octobercms.com/pricing" rel="noopener noreferrer"&gt;production license&lt;/a&gt; after the complimentary license, and continued updates require annual renewal. It fits projects built around October more directly than existing Laravel products needing a CMS module.&lt;/p&gt;

&lt;h2&gt;
  
  
  When PagibleAI fits
&lt;/h2&gt;

&lt;p&gt;PagibleAI keeps the CMS inside the Laravel application. It supplies structured content, media, page trees, versions, permissions, scheduling, search, delivery APIs and editorial automation. The application retains its domain rules, users, infrastructure and deployment, without a per-site CMS fee or mandatory frontend framework.&lt;/p&gt;

&lt;p&gt;This model suits SaaS products with customer-specific content, marketplaces and portals that connect editorial content to application data, and agencies running several sites or domains from one installation. The same published content can serve Blade templates, web applications and mobile clients. AI-assisted editing remains subject to the ordinary publishing controls.&lt;/p&gt;

&lt;p&gt;Statamic fits Git-centered content projects, while October CMS fits projects built around its website platform. PagibleAI fits teams that want the CMS to remain a Laravel component.&lt;/p&gt;

&lt;p&gt;For developers who already use Laravel as the product foundation, &lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;PagibleAI CMS&lt;/a&gt; is the most direct option of the three. The &lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;PagibleAI source code&lt;/a&gt; and &lt;a href="https://pagible.com/laravel-cms" rel="noopener noreferrer"&gt;Laravel CMS installation guide&lt;/a&gt; cover the next steps.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>cms</category>
      <category>opensource</category>
    </item>
    <item>
      <title>PagibleAI: A Cloud-Native Laravel CMS, Not Just a Container</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Thu, 23 Jul 2026 12:09:18 +0000</pubDate>
      <link>https://dev.to/aimeos/pagibleai-a-cloud-native-laravel-cms-not-just-a-container-c29</link>
      <guid>https://dev.to/aimeos/pagibleai-a-cloud-native-laravel-cms-not-just-a-container-c29</guid>
      <description>&lt;p&gt;A container changes how software is packaged. It says little about where that software keeps state or how it behaves when another instance comes online.&lt;/p&gt;

&lt;p&gt;A CMS that writes uploads to local disk, caches pages inside one process and runs background work during web requests is still tied to one machine, however neatly it has been containerized.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.cncf.io/about/who-we-are/" rel="noopener noreferrer"&gt;Cloud Native Computing Foundation&lt;/a&gt; defines cloud-native systems in terms of scalability, loose coupling, resilience, manageability and observability. It cites containers and microservices among the techniques used to achieve those properties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pagible.com/cloud-native-cms" rel="noopener noreferrer"&gt;PagibleAI CMS&lt;/a&gt; follows that model through Laravel's infrastructure contracts. Database connections, filesystem disks, cache stores, queues and broadcasting form the boundary between the CMS and the machine running it.&lt;/p&gt;

&lt;p&gt;A site can begin with SQLite and local files, then move to replicated application nodes, a managed database, object storage, shared cache and independent queue workers without altering its content model.&lt;/p&gt;

&lt;p&gt;“Fully cloud-native” here means that the CMS has no architectural dependency on a particular web server. Kubernetes is one possible runtime, not a requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  One application, one operating model
&lt;/h2&gt;

&lt;p&gt;PagibleAI installs as a Composer package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/pagible
php artisan cms:install
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installation turns an existing Laravel application into the CMS. It does not introduce a separate content service with its own authentication, deployment and monitoring model.&lt;/p&gt;

&lt;p&gt;PagibleAI uses the application's service container, Eloquent connections, authentication, middleware, filesystem disks, cache stores, queues and logging channels. Development and operations stay within the Laravel stack.&lt;/p&gt;

&lt;p&gt;Laravel serves as both the framework beneath the admin panel and the infrastructure abstraction layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clients → CDN → Load balancer → Laravel replicas
                                  ├── Managed database
                                  ├── Redis cache and locks
                                  ├── Object storage
                                  └── Queue broker → workers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same topology can run on AWS, Google Cloud, Azure, Kubernetes, conventional virtual machines or a managed Laravel platform. Provider-specific details remain in Laravel's configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Durable state stays off the web node
&lt;/h2&gt;

&lt;p&gt;Horizontal replication only works when the next request can land on any node. PagibleAI keeps durable state in shared infrastructure rather than in the web process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content in the database
&lt;/h3&gt;

&lt;p&gt;Pages, reusable elements, files and versions are Eloquent models. PagibleAI supports SQLite for a compact local installation and MySQL, MariaDB, PostgreSQL or SQL Server for production deployments.&lt;/p&gt;

&lt;p&gt;Every edit creates an immutable version snapshot. Editors work against the latest version while visitors receive the published one. Any replica can serve either view because the database, rather than the PHP process, owns that state. Laravel's read/write connections can place a managed primary and replicas behind the same CMS connection without introducing another database layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Media on a filesystem disk
&lt;/h3&gt;

&lt;p&gt;PagibleAI sends uploads through Laravel's filesystem abstraction. The default public disk is convenient on a laptop, while &lt;code&gt;CMS_DISK=s3&lt;/code&gt; can move the same media operations to Amazon S3 or another S3-compatible service. Laravel's &lt;a href="https://laravel.com/docs/13.x/filesystem" rel="noopener noreferrer"&gt;filesystem drivers&lt;/a&gt; also cover services such as Cloudflare R2, MinIO and DigitalOcean Spaces.&lt;/p&gt;

&lt;p&gt;Uploaded media is then independent of the web-container lifecycle. Replacement nodes need no copied volume, and a CDN can serve files without routing every byte through PHP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache and coordination
&lt;/h3&gt;

&lt;p&gt;PagibleAI's public page cache stores complete HTML responses. In a multi-node deployment, that cache moves from the default file store to a shared, lock-capable store such as Redis.&lt;/p&gt;

&lt;p&gt;The lock matters as much as the cached HTML. When a popular page expires, one renderer acquires the lease. Other requests can receive the stale entry during a short revalidation window instead of repeating the same query and rendering work across every replica.&lt;/p&gt;

&lt;p&gt;Fresh responses carry shared-cache directives such as &lt;code&gt;s-maxage&lt;/code&gt;, allowing a CDN to absorb public traffic before it reaches the application. Requests with a Laravel session or an &lt;code&gt;Authorization&lt;/code&gt; header bypass the public cache, so authenticated content is not accidentally promoted to a shared response.&lt;/p&gt;

&lt;p&gt;After a publication, deletion or access change commits, PagibleAI queues targeted invalidation work. If that job is delayed, the configured cache lifetime determines how long an old response can remain available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit first, then distribute
&lt;/h2&gt;

&lt;p&gt;Database writes and distributed side effects fail independently. An event emitted before commit may describe a change that later rolls back; a cache or search job may run after a temporary queue failure.&lt;/p&gt;

&lt;p&gt;PagibleAI starts these side effects after the database transaction commits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search reconciliation is dispatched only after the content transaction succeeds.&lt;/li&gt;
&lt;li&gt;Rendered-page invalidation is requested after commit and handled by a queue worker.&lt;/li&gt;
&lt;li&gt;Collaboration events are emitted after commit, so another editor never receives a change that the database later rejects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clients, caches and search indexes therefore do not observe writes that the database later rejects.&lt;/p&gt;

&lt;p&gt;The jobs use Laravel's &lt;a href="https://laravel.com/docs/13.x/queues" rel="noopener noreferrer"&gt;queue contract&lt;/a&gt;, so production can use Redis or Amazon SQS while development stays on a simpler connection. Workers scale independently from the web tier, with Laravel supplying retries, failed-job handling, supervision and deployment restarts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in search, external engine optional
&lt;/h2&gt;

&lt;p&gt;PagibleAI's &lt;a href="https://github.com/aimeos/pagible/blob/master/search/src/Scout/CmsEngine.php" rel="noopener noreferrer"&gt;Laravel Scout engine&lt;/a&gt; uses the full-text facilities already present in the selected database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FTS5 on SQLite&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MATCH ... AGAINST&lt;/code&gt; on MySQL and MariaDB&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tsvector&lt;/code&gt; on PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONTAINSTABLE&lt;/code&gt; on SQL Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Draft and published content receive separate index rows, preserving the same visibility boundary used by the CMS.&lt;/p&gt;

&lt;p&gt;The first production deployment therefore needs no separate search cluster. If a later workload justifies an external engine, Laravel Scout remains the extension point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless and server-rendered delivery
&lt;/h2&gt;

&lt;p&gt;Content is available through three delivery surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GraphQL administration API, used by the Vue editor and available to custom tools&lt;/li&gt;
&lt;li&gt;A read-only JSON:API for web applications, mobile clients and static-site pipelines&lt;/li&gt;
&lt;li&gt;Server-rendered Blade themes for sites that benefit from direct HTML delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three use the same content model. The editor and GraphQL endpoint can remain inside a private application network, the read-only API can sit behind an API gateway, and Blade output can be cached at the edge. Frontend delivery can scale independently without maintaining a second copy of editorial data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tenant context beyond the HTTP request
&lt;/h2&gt;

&lt;p&gt;PagibleAI uses single-database multi-tenancy. CMS models carry a &lt;code&gt;tenant_id&lt;/code&gt;, and a global Eloquent scope limits queries to the active tenant. Multi-domain routing can map separate page trees to separate domains.&lt;/p&gt;

&lt;p&gt;Search jobs retain the tenant they were created for. Page-cache keys include the tenant and domain. Realtime channels require both a matching tenant and the relevant view permission.&lt;/p&gt;

&lt;p&gt;That gives SaaS products and agencies one deployment and one shared database with application-level content isolation. It is not database-per-tenant isolation. Requirements that mandate a separate database for every customer need a different tenancy architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realtime and long-running processes
&lt;/h2&gt;

&lt;p&gt;When broadcasting is enabled, PagibleAI uses Laravel Reverb and Echo to notify other editors about saved, published, restored, moved or deleted content.&lt;/p&gt;

&lt;p&gt;The events carry the metadata needed to update a list. They do not turn the WebSocket connection into a second content-delivery API. An open detail view re-fetches changed content through GraphQL, and a client reloads its state after reconnecting because it may have missed events while the socket was unavailable.&lt;/p&gt;

&lt;p&gt;Laravel Octane and queue workers keep the application alive between requests or jobs. PagibleAI binds tenant and access state to scoped lifetimes, keeps GraphQL metadata on the request, and avoids a global user-ID permission cache. This prevents state from one execution leaking into the next under &lt;a href="https://laravel.com/docs/13.x/octane" rel="noopener noreferrer"&gt;Octane&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Optional Pulse metrics cover page requests, search, contact forms, JSON:API, GraphQL and MCP operations. Structured watch logs use the application's logging stack, while Laravel's health route can feed a load balancer or Kubernetes probe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring a distributed deployment
&lt;/h2&gt;

&lt;p&gt;PagibleAI's local defaults suit a single process. A distributed deployment replaces the node-local parts with shared services.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Small installation&lt;/th&gt;
&lt;th&gt;Distributed installation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;Managed MySQL, MariaDB, PostgreSQL or SQL Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;Local public disk&lt;/td&gt;
&lt;td&gt;S3-compatible object storage and CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page cache and locks&lt;/td&gt;
&lt;td&gt;File cache&lt;/td&gt;
&lt;td&gt;Shared Redis cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sessions&lt;/td&gt;
&lt;td&gt;Local or database&lt;/td&gt;
&lt;td&gt;Shared database or Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jobs&lt;/td&gt;
&lt;td&gt;Synchronous or database queue&lt;/td&gt;
&lt;td&gt;Redis or SQS with independent workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web runtime&lt;/td&gt;
&lt;td&gt;One PHP process&lt;/td&gt;
&lt;td&gt;Replicas behind a load balancer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live updates&lt;/td&gt;
&lt;td&gt;Disabled&lt;/td&gt;
&lt;td&gt;Reverb with shared production configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telemetry&lt;/td&gt;
&lt;td&gt;Local logs&lt;/td&gt;
&lt;td&gt;Centralized logs and optional Pulse metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A production environment may begin like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=pgsql
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

CMS_DISK=s3

# After installing and configuring Laravel Reverb
CMS_BROADCAST=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete-page cache selects its own store, so configure Redis explicitly for production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/cms/theme.php&lt;/span&gt;
&lt;span class="s1"&gt;'cache'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'APP_DEBUG'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'array'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'redis'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The infrastructure also needs a few standard operating rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build application code, Composer dependencies and published assets into an immutable release.&lt;/li&gt;
&lt;li&gt;Keep uploaded media off ephemeral web disks.&lt;/li&gt;
&lt;li&gt;Run queue workers separately, restart them during deployments and run only one scheduler.&lt;/li&gt;
&lt;li&gt;Ensure the CDN bypasses public HTML caching for session and authorization requests.&lt;/li&gt;
&lt;li&gt;Extend Laravel's health endpoint with database and cache diagnostics appropriate to your availability target.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;PagibleAI uses Laravel's &lt;a href="https://laravel.com/docs/13.x/cache" rel="noopener noreferrer"&gt;cache API&lt;/a&gt;, queues and filesystem directly, so the same operational tooling applies to the CMS and the rest of the application.&lt;/p&gt;

&lt;p&gt;The source is available in the &lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;PagibleAI GitHub repository&lt;/a&gt;, and the &lt;a href="https://pagible.com/install-pagibleai-cms" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt; covers the first deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What PagibleAI leaves to the deployment
&lt;/h2&gt;

&lt;p&gt;PagibleAI does not provision a VPC, tune PostgreSQL, choose a Redis topology or write Kubernetes manifests. The deployment team owns those choices.&lt;/p&gt;

&lt;p&gt;They remain deployment responsibilities. PagibleAI keeps them outside the content model and editorial workflow, allowing state to move to managed services, workers to split from the web tier and public responses to move toward the edge.&lt;/p&gt;

&lt;p&gt;The visible product includes structured content, versioning, AI-assisted editing, GraphQL, JSON:API and MCP tools. The deployment model rests on less visible choices: authoritative database state, replaceable storage, shared cache coordination, post-commit side effects, queued work and request isolation in long-running processes.&lt;/p&gt;

&lt;p&gt;The same &lt;a href="https://pagible.com/laravel-cms" rel="noopener noreferrer"&gt;PagibleAI CMS&lt;/a&gt; package and content model can run in one process or across a cluster.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>cloud</category>
      <category>opensource</category>
      <category>php</category>
    </item>
    <item>
      <title>How to customize Aimeos e-commerce projects without maintaining a fork</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Tue, 21 Jul 2026 11:28:22 +0000</pubDate>
      <link>https://dev.to/aimeos/how-to-customize-aimeos-e-commerce-projects-without-maintaining-a-fork-2904</link>
      <guid>https://dev.to/aimeos/how-to-customize-aimeos-e-commerce-projects-without-maintaining-a-fork-2904</guid>
      <description>&lt;p&gt;Editing a file under &lt;code&gt;vendor/&lt;/code&gt; can solve today's problem and create the next upgrade's problem.&lt;/p&gt;

&lt;p&gt;The first change usually looks harmless: move a block on the product page, add a checkout rule, adjust the way products are loaded. After a few more, the shop depends on a private fork and every Composer update begins with a three-way diff.&lt;/p&gt;

&lt;p&gt;Aimeos provides a separate place for each kind of change. Wording can stay in translation configuration, page composition in page configuration, markup in a template and business rules in decorators. Larger features can live in their own Composer package.&lt;/p&gt;

&lt;p&gt;When a new requirement arrives, start by finding the narrowest layer that can handle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the smallest extension point
&lt;/h2&gt;

&lt;p&gt;Before writing a class, identify the layer that owns the requirement.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Change a label, page size or feature switch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;config/shop.php&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add or remove a storefront component&lt;/td&gt;
&lt;td&gt;page configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change the Laravel page shell&lt;/td&gt;
&lt;td&gt;an overridden Blade view&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restyle the shop&lt;/td&gt;
&lt;td&gt;a custom theme&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change component markup&lt;/td&gt;
&lt;td&gt;a template override&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store project-specific product data&lt;/td&gt;
&lt;td&gt;properties or attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add behavior around existing logic&lt;/td&gt;
&lt;td&gt;a decorator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replace an implementation completely&lt;/td&gt;
&lt;td&gt;a configured class replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add new storage, behavior or an integration&lt;/td&gt;
&lt;td&gt;a project-specific Aimeos extension&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use the first row that solves the problem. There is little value in creating a subclass for a configuration change or copying a controller when a decorator can add the required behavior. Related project code is also easier to follow when it lives in one extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with configuration
&lt;/h2&gt;

&lt;p&gt;The Laravel integration exposes the shop configuration in &lt;code&gt;config/shop.php&lt;/code&gt;. Its nested arrays follow the structure of Aimeos components and controllers, so the location of a setting identifies the part of the system it affects.&lt;/p&gt;

&lt;p&gt;Suppose a store needs 24 products per page, no add-to-basket button in product lists, a two-level mega menu and “Brands” instead of “Suppliers”. The relevant configuration is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'client'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'html'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'lists'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'basket-add'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'size'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;

&lt;span class="s1"&gt;'controller'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'frontend'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'levels-always'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;

&lt;span class="s1"&gt;'i18n'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'en'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'client'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'Suppliers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Brands'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No service provider, listener or copied component is involved.&lt;/p&gt;

&lt;p&gt;Some structural changes are environment switches. Multi-language routes, vendor-specific sites and seller registration can be enabled without rebuilding the routing layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOP_MULTILOCALE=true
SHOP_MULTISHOP=true
SHOP_REGISTRATION=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For many projects, &lt;code&gt;config/shop.php&lt;/code&gt; is where customization starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compose pages from components
&lt;/h2&gt;

&lt;p&gt;A storefront page is assembled from components. A product detail page can contain locale selection, the mini basket, category navigation, search, a stage area, the product itself and session-based lists such as recently viewed products.&lt;/p&gt;

&lt;p&gt;The list lives in &lt;code&gt;config/shop.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'page'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'catalog-detail'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'locale/select'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'basket/mini'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog/tree'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog/search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog/stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'catalog/detail'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This version leaves out &lt;code&gt;catalog/session&lt;/code&gt;. The page no longer prepares the recently viewed and pinned-product area, but the product-detail component remains untouched.&lt;/p&gt;

&lt;p&gt;You can also add an existing component to a page, or create a Laravel route and render the required Aimeos components through the &lt;code&gt;Shop&lt;/code&gt; facade.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aimeos.org/docs/latest/laravel/extend/" rel="noopener noreferrer"&gt;Laravel extension guide&lt;/a&gt; documents the available page sections, routes and facade integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the page shell, markup and theme separate
&lt;/h2&gt;

&lt;p&gt;Aimeos separates presentation into three layers. Blade views define the surrounding Laravel page, component templates generate the storefront markup, and themes provide CSS, JavaScript, fonts and images.&lt;/p&gt;

&lt;p&gt;To change the complete product-detail page shell, copy the corresponding package view to the application's vendor-view directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/vendor/shop/catalog/detail.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel prefers the application copy, leaving the package file untouched.&lt;/p&gt;

&lt;p&gt;If the page shell is already correct but the product markup is not, override only the relevant template in the project extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;templates/client/html/catalog/detail/body.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An identically named project template takes precedence over the default. A custom image gallery may need only &lt;code&gt;catalog/detail/image.php&lt;/code&gt;; it does not require a copy of the entire detail component.&lt;/p&gt;

&lt;p&gt;If the HTML structure is already right, a theme is enough. Aimeos keeps assets such as &lt;code&gt;catalog-detail.css&lt;/code&gt; and &lt;code&gt;basket-mini.js&lt;/code&gt; per component, so pages load the assets for the components they use.&lt;/p&gt;

&lt;p&gt;The size of the override matters during upgrades. Replacing &lt;code&gt;image.php&lt;/code&gt; instead of &lt;code&gt;body.php&lt;/code&gt;, for example, leaves less upstream code to compare.&lt;/p&gt;

&lt;p&gt;During development, clear the Aimeos and compiled Blade caches if configuration or template changes do not appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan aimeos:clear
php artisan view:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official guides cover both &lt;a href="https://aimeos.org/docs/latest/frontend/html/overwrite-templates/" rel="noopener noreferrer"&gt;template overrides&lt;/a&gt; and &lt;a href="https://aimeos.org/docs/latest/frontend/html/create-themes/" rel="noopener noreferrer"&gt;custom themes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add business rules with decorators
&lt;/h2&gt;

&lt;p&gt;Many project rules only need to run around existing behavior. Typical examples include a regional availability check, an audit event, data from an external service or validation before an item is stored.&lt;/p&gt;

&lt;p&gt;A decorator wraps the existing object, changes only the relevant methods and delegates everything else.&lt;/p&gt;

&lt;p&gt;For example, a product-controller decorator can check products retrieved individually through &lt;code&gt;get()&lt;/code&gt; against an application service owned by the Laravel project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Aimeos\Controller\Frontend\Product\Decorator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Commerce\AvailabilityRule&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\MShop\Product\Item\Iface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Availability&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Iface&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AvailabilityRule&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertPurchasable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AvailabilityRule&lt;/code&gt; is ordinary Laravel application code. The decorator connects it to the Aimeos product controller.&lt;/p&gt;

&lt;p&gt;The class belongs at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/Controller/Frontend/Product/Decorator/Availability.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register it in &lt;code&gt;config/shop.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'controller'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'frontend'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'product'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'decorators'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'local'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Availability'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;code&gt;get()&lt;/code&gt; changes. Product searches, aggregation and the remaining controller API continue through the original implementation. This example therefore guards direct product retrieval only. If the rule determines whether a product may be purchased, enforce it again at basket or checkout level.&lt;/p&gt;

&lt;p&gt;HTML clients and data managers support the same pattern. Several decorators can be combined without collecting unrelated rules in one project class.&lt;/p&gt;

&lt;p&gt;When the standard behavior is unsuitable, Aimeos factories also support named replacements. Setting &lt;code&gt;controller/frontend/product/name&lt;/code&gt; to &lt;code&gt;Project&lt;/code&gt;, for example, selects &lt;code&gt;Aimeos\Controller\Frontend\Product\Project&lt;/code&gt;. This is useful when a decorator would have to replace most of the original implementation anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put larger customizations in one package
&lt;/h2&gt;

&lt;p&gt;Once a customization contains several classes, templates, translations or database changes, it should become a project-specific Aimeos extension.&lt;/p&gt;

&lt;p&gt;Before extending a core table, check whether the requirement fits an Aimeos property, attribute or related domain item. Much project-specific product data can be stored without changing the core schema.&lt;/p&gt;

&lt;p&gt;The standalone distribution already declares &lt;code&gt;packages/*&lt;/code&gt; as a Composer path repository. An extension can live there during development and be installed like any other dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require acme/shop-extension
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A typical project extension contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/shop-extension/
├── composer.json
├── manifest.php
├── config/
├── i18n/
├── setup/
├── src/
├── templates/
└── themes/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manifest registers the resources contributed by the package. The &lt;code&gt;setup/&lt;/code&gt; directory carries schema updates, Composer handles autoloading, and the extension can be versioned independently from both Laravel and Aimeos.&lt;/p&gt;

&lt;p&gt;For a single shop, this keeps its Aimeos-specific code in one place. Organizations running several shops can use the same package to share an integration, theme or business rule between applications.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aimeos.org/docs/latest/developer/extensions/" rel="noopener noreferrer"&gt;extension documentation&lt;/a&gt; explains manifests and package structure, while the &lt;a href="https://aimeos.org/extensions/" rel="noopener noreferrer"&gt;extension generator&lt;/a&gt; creates the initial files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know when to replace the HTML frontend
&lt;/h2&gt;

&lt;p&gt;Template overrides work well while the application still fits the component model. If nearly every page needs replacing, or the same commerce backend must serve web, mobile and in-store clients, the APIs are usually the cleaner option.&lt;/p&gt;

&lt;p&gt;Aimeos exposes storefront data through JSON:API and administration through GraphQL. The product, price, stock, basket and order logic can remain in place while a new client replaces the presentation.&lt;/p&gt;

&lt;p&gt;A team does not have to make that change all at once. It can keep the working storefront, override a few templates and use the APIs only for channels that need a separate interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the structure costs
&lt;/h2&gt;

&lt;p&gt;The first extension takes some orientation. Configuration paths correspond to class and template paths, and the naming convention is more explicit than a generic Laravel hook.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;controller/frontend/product/decorators/local&lt;/code&gt; has led to the product controller's decorator directory, the same relationship repeats throughout the platform. The paths make it possible to see who owns the behavior and how the project changed it.&lt;/p&gt;

&lt;p&gt;Separation does not make custom code immune to upstream changes. Templates, decorators and replacement classes should still be reviewed during major upgrades, but the affected surface is explicit and confined to the project extension.&lt;/p&gt;

&lt;p&gt;Upstream code stays in &lt;code&gt;vendor/&lt;/code&gt;, project code stays in the project extension, and updates require a focused compatibility review rather than a source-code merge.&lt;/p&gt;

&lt;p&gt;Each kind of change has an obvious home. By using the narrowest one that fits, a shop can move a long way from the Aimeos defaults without becoming a fork.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>ecommerce</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PagibleAI: The Best Headless CMS for Laravel</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Thu, 16 Jul 2026 11:23:33 +0000</pubDate>
      <link>https://dev.to/aimeos/pagibleai-the-best-headless-cms-for-laravel-4koo</link>
      <guid>https://dev.to/aimeos/pagibleai-the-best-headless-cms-for-laravel-4koo</guid>
      <description>&lt;p&gt;Headless is supposed to loosen the frontend. Too often, it merely moves the constraint somewhere else.&lt;/p&gt;

&lt;p&gt;A hosted platform places content behind a remote service. A toolkit leaves the delivery API and publishing model to the application. An admin framework can turn a headless project into a CMS development project before the frontend has even begun.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;PagibleAI CMS&lt;/a&gt; keeps the content system inside Laravel, exposes published material through a standard API and leaves the frontend entirely open.&lt;/p&gt;

&lt;p&gt;Structured content, reusable elements, media, drafts, immutable versions and scheduled publishing are already part of the package.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CMS remains part of the application
&lt;/h2&gt;

&lt;p&gt;PagibleAI installs into an existing Laravel project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/pagible
php artisan cms:install
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CMS does not live behind a vendor account or inside a second application with its own users, permissions and release cycle. It shares the Laravel project’s database, authentication, storage, cache and deployment process.&lt;/p&gt;

&lt;p&gt;The frontend is decoupled; deployment and operations remain consolidated.&lt;/p&gt;

&lt;p&gt;The useful boundary in a headless system lies between content and presentation, not between a Laravel application and its own content.&lt;/p&gt;

&lt;p&gt;A remote CMS can be the right decision when outsourcing infrastructure is the priority. It is less persuasive when the project already has a capable application platform and the additional service creates another place where business rules must be translated, synchronized and monitored.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the package already settles
&lt;/h2&gt;

&lt;p&gt;Several decisions precede the first frontend request. PagibleAI makes them explicit:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;PagibleAI’s answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Public delivery&lt;/td&gt;
&lt;td&gt;Read-only JSON:API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Editorial operations&lt;/td&gt;
&lt;td&gt;Administrative GraphQL API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content model&lt;/td&gt;
&lt;td&gt;Pages, reusable elements, files and versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publishing&lt;/td&gt;
&lt;td&gt;Drafts, scheduling, history and restoration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site structure&lt;/td&gt;
&lt;td&gt;Hierarchical page trees for navigation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Any API client, with Blade available when useful&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reach&lt;/td&gt;
&lt;td&gt;Multiple domains and languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;Full-text search through Laravel Scout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ownership&lt;/td&gt;
&lt;td&gt;Open source and self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;Optional AI tools and an MCP interface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;PagibleAI documents this separation between editorial operations and public delivery in the &lt;a href="https://pagible.com/headless-cms" rel="noopener noreferrer"&gt;PagibleAI headless CMS guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Editors manage versions and reusable content through one publishing system, while frontends receive a stable stream of published material. You extend the CMS instead of finishing its foundations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Laravel alternatives
&lt;/h2&gt;

&lt;p&gt;The Laravel shortlist usually includes Statamic, Twill and Filament. The practical difference is how much work remains after installation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Best suited to&lt;/th&gt;
&lt;th&gt;What remains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PagibleAI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Most headless Laravel applications&lt;/td&gt;
&lt;td&gt;All included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Statamic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams wanting a mature commercial CMS and paid support&lt;/td&gt;
&lt;td&gt;A Pro license for headless features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Twill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bespoke editorial systems with custom models&lt;/td&gt;
&lt;td&gt;The public delivery API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Filament&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom back offices and administration tools&lt;/td&gt;
&lt;td&gt;The CMS itself&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Statamic offers a control panel, REST and GraphQL, but requires a paid &lt;a href="https://statamic.com/pricing?lang=en" rel="noopener noreferrer"&gt;Statamic Pro&lt;/a&gt; license for headless delivery and multi-user publishing.&lt;/p&gt;

&lt;p&gt;Twill supplies editorial components and flexible content modules, while leaving &lt;a href="https://twillcms.com/docs/getting-started/installation.html" rel="noopener noreferrer"&gt;frontend routes and API endpoints to the developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Filament provides &lt;a href="https://filamentphp.com/docs/5.x/getting-started" rel="noopener noreferrer"&gt;CRUD interfaces for Eloquent models&lt;/a&gt;; publication states, versions, previews and content delivery remain your own concerns.&lt;/p&gt;

&lt;p&gt;PagibleAI is the only option in this group that combines a complete open-source CMS with a built-in public delivery API - without a paid headless tier or a custom delivery layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  A deliberate boundary between editing and delivery
&lt;/h2&gt;

&lt;p&gt;The public and editorial APIs have different roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL serves the administration layer, where editors and custom tools need precise queries, relationships and mutations&lt;/li&gt;
&lt;li&gt;Public frontends receive published content through a high performance read-only JSON API following the JSON:API standard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The delivery API has a narrow promise: return content that is ready to be shown. A frontend does not need to interpret editorial permissions or infer whether a record is still a draft. The public contract stays read-only and editorial complexity remains behind GraphQL.&lt;/p&gt;

&lt;p&gt;The choice of frontend belongs to your project. Nuxt, React, VueJS, a native application or another service can consume the same published content. If parts of the site is better served directly by Laravel, Blade remains available without requiring a second content system.&lt;/p&gt;

&lt;p&gt;Headless delivery becomes a choice of presentation, not a demand to split every project into separate applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content that survives the current frontend
&lt;/h2&gt;

&lt;p&gt;A headless CMS should preserve structure without smuggling presentation into the content.&lt;/p&gt;

&lt;p&gt;PagibleAI separates pages, reusable elements, files and versions. A product statement, author profile, legal notice or call to action can be maintained once and placed wherever it belongs. Each frontend decides how to present it.&lt;/p&gt;

&lt;p&gt;An editor can update a product statement once and publish it. The same approved version then becomes available to a Nuxt storefront, a mobile application and a customer portal, while each frontend controls its presentation.&lt;/p&gt;

&lt;p&gt;The page tree supplies hierarchy for navigation, while shared elements remain reusable beyond an individual page. Editors retain a coherent view of the site without binding its content to one template system.&lt;/p&gt;

&lt;p&gt;That separation also governs publishing. Every editorial save creates a snapshot. Editors work with the latest version; public consumers continue to receive the published one. A replacement can be reviewed, scheduled or discarded without disturbing the live experience.&lt;/p&gt;

&lt;p&gt;When several frontends depend on the same CMS, this separation becomes essential. Publication is decided once, at the source, rather than interpreted independently by every consumer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unglamorous work is already done
&lt;/h2&gt;

&lt;p&gt;The attraction of building a CMS from smaller Laravel components is strongest at the beginning. A model, migration and administration form can be produced quickly.&lt;/p&gt;

&lt;p&gt;The expensive work comes later: search, restoration, media relationships, translations, page movement, safe previews, publication scheduling and API compatibility.&lt;/p&gt;

&lt;p&gt;PagibleAI treats those concerns as part of the product:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full-text search works with SQLite, MySQL, PostgreSQL and SQL Server&lt;/li&gt;
&lt;li&gt;Multiple domains and languages can share one installation&lt;/li&gt;
&lt;li&gt;Tenant-scoped content supports projects operating several sites from the same Laravel deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these capabilities is especially fashionable but all of them become expensive when discovered late.&lt;/p&gt;

&lt;p&gt;PagibleAI also includes optional AI-assisted editing and a full MCP interface, but neither is required for the headless publishing workflow.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://pagible.com/features" rel="noopener noreferrer"&gt;PagibleAI feature overview&lt;/a&gt; documents these capabilities in greater detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where PagibleAI may not be the answer
&lt;/h2&gt;

&lt;p&gt;It is self-hosted and your team operates it as part of the Laravel application. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the primary requirement is to hand the entire CMS operation to a vendor, a managed platform is the more natural choice.&lt;/li&gt;
&lt;li&gt;Public delivery is centred on JSON:API for performance and scalability reasons, while GraphQL serves editorial work. A project committed specifically to a public GraphQL content API would need to add that layer.&lt;/li&gt;
&lt;li&gt;Multi-tenancy uses a shared database. Applications requiring a separate database for every tenant fall outside the intended model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most Laravel teams seeking a self-hosted headless CMS, the trade is still favourable: the content and publishing system arrives complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better use of development time
&lt;/h2&gt;

&lt;p&gt;The real cost of a headless CMS is the engineering it diverts from the product.&lt;/p&gt;

&lt;p&gt;PagibleAI handles content structure, editorial workflow and publication state. Your team shapes the frontend, its design, interactions, performance and relationship with the rest of the application.&lt;/p&gt;

&lt;p&gt;Editors get a dependable publishing environment, frontends consume consistent published content, and developers decide how that content becomes a product. The CMS stays close to Laravel without tying the presentation to it.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;PagibleAI source code&lt;/a&gt; is available on GitHub.&lt;/p&gt;

&lt;p&gt;For a Laravel team that wants a headless CMS without also building one, PagibleAI is the strongest option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is PagibleAI CMS?
&lt;/h3&gt;

&lt;p&gt;PagibleAI CMS is an open-source, self-hosted headless CMS for Laravel. It provides structured content, reusable elements, media management, drafts, immutable versions, scheduled publishing and public content delivery within an existing Laravel application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is PagibleAI a headless CMS?
&lt;/h3&gt;

&lt;p&gt;Yes. PagibleAI separates content management from presentation. Editors manage content through the administration interface, while websites, mobile applications and other clients retrieve published content through a read-only JSON:API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does PagibleAI require a separate hosted service?
&lt;/h3&gt;

&lt;p&gt;No. PagibleAI runs inside your Laravel application and uses its database, authentication, storage, cache and deployment infrastructure. Content does not need to be stored in a separate vendor-controlled platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which frontends can use PagibleAI?
&lt;/h3&gt;

&lt;p&gt;Any frontend capable of consuming an HTTP API can use PagibleAI. Common choices include Nuxt, Vue, React, native mobile applications and external services. Laravel projects can also render selected pages with Blade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which APIs does PagibleAI provide?
&lt;/h3&gt;

&lt;p&gt;PagibleAI provides two APIs with distinct responsibilities. Its read-only JSON:API delivers published content to public frontends. Its GraphQL API supports editorial administration, including content queries, relationships and mutations.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does publishing work in PagibleAI?
&lt;/h3&gt;

&lt;p&gt;Each editorial save creates an immutable version. Editors can review, restore or schedule versions without immediately changing the public content. Frontends continue to receive the currently published version until a replacement is published.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can content be shared between multiple frontends?
&lt;/h3&gt;

&lt;p&gt;Yes. Pages, reusable elements and files are stored independently of a particular frontend. The same published content can therefore supply a website, mobile application, storefront or customer portal while each client controls its own presentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does PagibleAI support multiple websites and languages?
&lt;/h3&gt;

&lt;p&gt;Yes. One installation can manage content for multiple domains and languages. It also supports tenant-scoped content for applications that operate several sites from one Laravel deployment using a shared database.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is PagibleAI different from Filament or Twill?
&lt;/h3&gt;

&lt;p&gt;Filament is an administration framework rather than a complete CMS, so content versioning, publishing workflows and delivery APIs must be implemented separately. Twill provides editorial components and flexible content modules but leaves public routes and API delivery to the application. PagibleAI includes both the publishing system and a public content API.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is PagibleAI different from Statamic?
&lt;/h3&gt;

&lt;p&gt;Both products can support headless Laravel projects. Statamic is a commercial CMS whose headless and multi-user capabilities require a Pro license. PagibleAI is open source and includes headless content delivery without a paid tier.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>headlesscms</category>
      <category>php</category>
      <category>ai</category>
    </item>
    <item>
      <title>Aimeos: The Headless E-Commerce Framework for Laravel</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Sat, 04 Jul 2026 16:58:52 +0000</pubDate>
      <link>https://dev.to/aimeos/aimeos-the-headless-e-commerce-framework-for-laravel-232j</link>
      <guid>https://dev.to/aimeos/aimeos-the-headless-e-commerce-framework-for-laravel-232j</guid>
      <description>&lt;p&gt;Laravel developers rarely need help building a storefront. Given a familiar stack, they can ship one with Blade, Livewire, Vue, React, Next.js, Nuxt, or a mobile client without much ceremony. The harder question is what happens after the first version is live, when the business starts asking for regional catalogs, customer-specific prices, subscriptions, stock rules, marketplace workflows, imports, exports, payment integrations, and an admin experience that non-developers can use every day.&lt;/p&gt;

&lt;p&gt;That is the point where many lightweight e-commerce packages begin to show their limits. They are pleasant while the model is simple, but the custom code around them grows quickly once the shop becomes central to the business, which is why Aimeos should be the default starting point when e-commerce is expected to become a serious part of a Laravel application rather than a small feature beside it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://aimeos.org/laravel-headless-ecommerce" rel="noopener noreferrer"&gt;Aimeos&lt;/a&gt; approaches the problem from the stronger direction: it gives Laravel a mature e-commerce engine first, then leaves the presentation layer open.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aimeos is not just a cart, a product table, and a checkout flow. It brings catalog management, basket handling, checkout, orders, customers, stock, suppliers, services, subscriptions, scheduled jobs, imports, a full administration interface, a JSON REST API for storefronts, and a GraphQL API for administration. More importantly, it does all of this without forcing Laravel to disappear behind a separate platform.&lt;/p&gt;

&lt;p&gt;That makes Aimeos the clearer favorite for ambitious Laravel e-commerce projects. Lunar PHP and Laravel Shopper both have useful places in the ecosystem, but Aimeos is the one that starts with the broader e-commerce model, the operational admin, the APIs, and the growth path already in place.&lt;/p&gt;

&lt;p&gt;To install the Aimeos headless distribution, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project aimeos/aimeos-headless aimeos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Short Version
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Laravel&lt;/td&gt;
&lt;td&gt;Application structure, routing, authentication, sessions, cache, logging, mail, queues, policies, and deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aimeos&lt;/td&gt;
&lt;td&gt;Catalog, prices, stock, basket, checkout, orders, services, subscriptions, jobs, imports, APIs, and administration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storefront&lt;/td&gt;
&lt;td&gt;Blade, Livewire, Vue, React, Next.js, Nuxt, mobile apps, partner portals, or any other client&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That division is the real argument for choosing Aimeos first. Laravel remains the application, Aimeos becomes the e-commerce engine, and the frontend can evolve without turning every business rule into custom application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Remains The Application, Not The Shopping Cart
&lt;/h2&gt;

&lt;p&gt;The best part of Aimeos in a Laravel project is not only the feature set, but the boundary it draws. Laravel continues to own the application structure: routing, authentication, sessions, cache, logging, configuration, mail, queues, policies, and deployment. Aimeos takes responsibility for the e-commerce domain, where product data, prices, baskets, stock, orders, services, and subscriptions need a model that has already survived real complexity.&lt;/p&gt;

&lt;p&gt;That separation is what makes Aimeos especially suitable for headless e-commerce. The storefront can change without rewriting the engine beneath it, while the e-commerce layer remains deep enough for the business requirements that usually arrive later. A team can start with a conventional Laravel storefront and still have a path toward a PWA, a mobile app, a B2B portal, a marketplace frontend, or partner-facing API clients.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laravel application
    -&amp;gt; routing, auth, cache, sessions, queues, mail, policies

Aimeos e-commerce engine
    -&amp;gt; catalog, prices, stock, basket, checkout, orders, admin

APIs
    -&amp;gt; JSON:API for storefronts
    -&amp;gt; GraphQL for administration

Clients
    -&amp;gt; Blade, Livewire, Vue, React, Next.js, Nuxt, mobile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may sound simple, but it is exactly the division many e-commerce projects fail to protect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless Without An Unfinished Back Office
&lt;/h2&gt;

&lt;p&gt;Headless e-commerce is often described as frontend freedom, although that framing leaves out the part that matters most in production. A custom storefront is only useful if the people running the business can still manage products, prices, orders, content, stock, and customer data without waiting for developers to edit database rows or build internal tools from scratch.&lt;/p&gt;

&lt;p&gt;Aimeos avoids that trap because its headless APIs sit beside an existing administration system rather than replacing it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aimeos part&lt;/th&gt;
&lt;th&gt;Why it matters in a headless setup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JSON REST API&lt;/td&gt;
&lt;td&gt;Custom storefronts can work against the e-commerce engine without being tied to one frontend stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GraphQL admin API&lt;/td&gt;
&lt;td&gt;Administration and automation can access shop data through a structured API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard admin&lt;/td&gt;
&lt;td&gt;Operations teams still have a usable interface for daily work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jobs and imports&lt;/td&gt;
&lt;td&gt;Product data, stock updates, and scheduled processes do not have to be invented around the edges&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That balance is one of the main reasons Aimeos feels different from thinner Laravel e-commerce packages. It treats the frontend as replaceable, but it does not treat the e-commerce operation as an exercise left to the application team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built For The Moment The Shop Becomes A Platform
&lt;/h2&gt;

&lt;p&gt;A simple store can survive on a simple package, and there is nothing wrong with that. The reason to choose Aimeos is that many Laravel e-commerce projects do not stay simple for very long. A brand expands into multiple regions, a B2C shop gains B2B accounts, one catalog becomes several catalogs, a single seller model becomes a marketplace, or the product data grows large enough that imports, indexing, and caching become architectural concerns rather than background tasks.&lt;/p&gt;

&lt;p&gt;That is where Aimeos starts to pay for its additional depth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multi-site setups where one installation serves several channels or regions&lt;/li&gt;
&lt;li&gt;B2B projects with customer-specific prices, visibility, or ordering behavior&lt;/li&gt;
&lt;li&gt;marketplace models where vendors, products, orders, and payments need clearer boundaries&lt;/li&gt;
&lt;li&gt;subscription-oriented projects where recurring processes must be part of the e-commerce model&lt;/li&gt;
&lt;li&gt;large catalogs where indexing, imports, caching, and operational tooling matter early&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aimeos is built for those situations. Its multi-site capabilities, broad e-commerce model, marketplace and B2B orientation, subscription support, import and job infrastructure, and scaling options make it the stronger foundation for projects where e-commerce is not an add-on feature but the system the business depends on.&lt;/p&gt;

&lt;p&gt;The tradeoff is that Aimeos has more concepts to learn than a smaller package. That is not a weakness if the project is expected to grow, because the complexity exists either way; the choice is whether it lives in a framework designed for e-commerce or in custom application code that accumulates around a package that was never meant to carry that much responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Aimeos Comes Out Ahead Of Lunar PHP And Laravel Shopper
&lt;/h2&gt;

&lt;p&gt;Lunar PHP and Laravel Shopper are both useful Laravel e-commerce projects, but they are narrower choices. The practical question is not whether they can work, because they can, but whether they give a Laravel team enough e-commerce depth before the business starts asking for more complex catalogs, B2B rules, marketplace behavior, subscriptions, imports, operational tooling, and multiple storefronts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;th&gt;What stands out&lt;/th&gt;
&lt;th&gt;Why Aimeos is favored&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Aimeos&lt;/td&gt;
&lt;td&gt;Larger e-commerce platforms, B2B, marketplaces, multi-site setups, complex catalogs, and projects expected to scale&lt;/td&gt;
&lt;td&gt;A mature e-commerce engine with APIs, admin, jobs, imports, subscriptions, and operational depth&lt;/td&gt;
&lt;td&gt;It is the strongest default when e-commerce is core to the business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar PHP&lt;/td&gt;
&lt;td&gt;Custom Laravel stores where an Eloquent-first development style is the priority&lt;/td&gt;
&lt;td&gt;A familiar Laravel feel with clean developer experience&lt;/td&gt;
&lt;td&gt;Aimeos gives more platform depth when requirements move beyond a custom store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laravel Shopper&lt;/td&gt;
&lt;td&gt;Existing Laravel apps that need package-style e-commerce building blocks&lt;/td&gt;
&lt;td&gt;A Laravel-friendly, Filament-based approach with swappable models and composable packages&lt;/td&gt;
&lt;td&gt;Aimeos is stronger when the project needs a complete e-commerce engine instead of building blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Lunar PHP is attractive when the development team wants the e-commerce layer to feel as close to Laravel conventions as possible. Its Eloquent-first model and Laravel-native style make sense for teams that want a custom store and expect to shape more of the surrounding business logic themselves, although that strength becomes a limitation when the project needs broader platform behavior rather than a Laravel-shaped e-commerce package.&lt;/p&gt;

&lt;p&gt;Laravel Shopper is appealing from a different angle. It is package-oriented, uses familiar Laravel ecosystem tools, and fits teams that want to add e-commerce capabilities to an existing application without adopting a heavier e-commerce platform, although Aimeos is the stronger option when the e-commerce layer should become durable infrastructure instead of a set of adaptable building blocks.&lt;/p&gt;

&lt;p&gt;Aimeos is the clearer favorite when the e-commerce system itself needs depth from the beginning. If the roadmap includes B2B rules, multiple storefronts, marketplace behavior, subscriptions, large imports, operational administration, or very large catalogs, Aimeos gives the Laravel team more of the foundation upfront rather than asking them to build it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Case For Aimeos
&lt;/h2&gt;

&lt;p&gt;The strongest argument for Aimeos is not simply that it is headless, because many tools can make that claim. The stronger argument is that Aimeos combines headless flexibility with a serious e-commerce core, a working admin, Laravel integration, and enough architectural room for projects that become more demanding over time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Choose Aimeos when the shop is expected to become a platform,
and treat smaller packages as niche choices for simpler stores.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That combination is difficult to replace. A thin package may feel faster at the beginning, while a hosted platform may remove too much control from a Laravel team that wants to own its application. Aimeos occupies the strongest middle ground: it gives Laravel developers a real e-commerce framework without taking away the freedom to build the customer experience in the stack that suits the product.&lt;/p&gt;

&lt;p&gt;For small stores, Aimeos may be more power than necessary. For ambitious Laravel e-commerce projects, especially those likely to move into B2B, marketplace, multi-site, subscription, or high-volume catalog territory, that power is exactly the reason Aimeos should be the preferred choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aimeos.org/laravel-headless-ecommerce" rel="noopener noreferrer"&gt;Aimeos headless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aimeos/aimeos-headless" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aimeos.org/docs" rel="noopener noreferrer"&gt;Aimeos documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravel</category>
      <category>ecommerce</category>
      <category>php</category>
      <category>headless</category>
    </item>
    <item>
      <title>Aimeos Prisma 0.5: a sturdier PHP layer for AI providers</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Tue, 30 Jun 2026 10:11:09 +0000</pubDate>
      <link>https://dev.to/aimeos/aimeos-prisma-05-a-sturdier-php-layer-for-ai-providers-n7i</link>
      <guid>https://dev.to/aimeos/aimeos-prisma-05-a-sturdier-php-layer-for-ai-providers-n7i</guid>
      <description>&lt;p&gt;Most AI integrations do not fail because the first provider is hard to call. They become awkward later, when the application has to speak several dialects at once.&lt;/p&gt;

&lt;p&gt;One endpoint generates text. Another returns embeddings. A third handles transcription. Image generation arrives with its own payload shape, its own errors, and its own idea of metadata. Add web search, tool calling, local models, or an OpenAI-compatible gateway, and the useful application code starts to disappear behind provider plumbing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aimeos/prisma" rel="noopener noreferrer"&gt;Aimeos Prisma&lt;/a&gt; exists to keep that boundary small. It gives PHP applications one API across text, image, audio, and video providers, while still leaving room for provider-specific options when they are needed.&lt;/p&gt;

&lt;p&gt;The 0.5 release makes that layer more suitable for real applications: streamed responses, conversation history, stronger schema support, request observation, better test doubles, safer response handling, and more provider coverage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/prisma
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The API shape
&lt;/h2&gt;

&lt;p&gt;Prisma is a framework-agnostic PHP 8.2+ package. It is MIT-licensed, uses Guzzle internally, and keeps the calling pattern consistent across provider types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Summarize the benefits of renewable energy'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stabilityai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'STABILITYAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;imagine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a clean product photo of a ceramic coffee cup'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$transcript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deepgram'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DEEPGRAM_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;transcribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$audioFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;video&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gemini'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GEMINI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$videoFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provider name changes. The surrounding application shape does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming belongs in the core API
&lt;/h2&gt;

&lt;p&gt;For user-facing tools, waiting for a full model response is often the wrong interaction. Prisma 0.5 adds &lt;code&gt;stream()&lt;/code&gt; as a text capability instead of treating it as a separate integration path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stream'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Write a short launch announcement for our PHP package'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$full&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;output&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Streaming keeps the same configuration surface as &lt;code&gt;write()&lt;/code&gt;: model selection, system prompts, tools, prior messages, and provider options all travel through the same provider object.&lt;/p&gt;

&lt;p&gt;In Laravel, it can be handed directly to &lt;code&gt;response()-&amp;gt;eventStream()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/chat'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'services.openai'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stream'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Explain event sourcing in plain English'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;eventStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$chunk&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is one operational rule: consume the stream before reading body-derived metadata. Usage, citations, tool steps, finish reason, and response metadata are complete only after the stream has been drained. Rate-limit data from headers is available immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conversation history without a second abstraction
&lt;/h2&gt;

&lt;p&gt;Chat history now lives in &lt;code&gt;withMessages()&lt;/code&gt;. The current prompt passed to &lt;code&gt;write()&lt;/code&gt;, &lt;code&gt;stream()&lt;/code&gt;, or &lt;code&gt;structure()&lt;/code&gt; becomes the next user turn.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'anthropic'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ANTHROPIC_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withSystemPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'You are a concise technical assistant.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withMessages&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'I need a laptop recommendation.'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'assistant'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'What is your budget and workload?'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Around 1500 EUR, mostly PHP development and light video editing.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For multimodal providers, user turns can also carry files, subject to each provider's file support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured output is stricter when it can be, explicit when it cannot
&lt;/h2&gt;

&lt;p&gt;Structured output is most useful when the code can state what it expects and then check what it received. Prisma 0.5 improves both sides.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Schema\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ticket'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'priority'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'low'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'normal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'high'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'tags'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'structure'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Extract a support ticket from: Checkout is broken for EU cards'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;structured&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, Prisma uses the provider's native structured-output mode when one exists. If a schema is too large or deeply nested for that mode, pass &lt;code&gt;['mode' =&amp;gt; 'json']&lt;/code&gt; and Prisma will embed the schema in the prompt and parse the returned JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Extract a support ticket'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mode'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schema builder also gained unions, reusable definitions, references, and validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Schema\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'order'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'billing'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Address'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'shipping'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Address'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'discount'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;anyOf&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Address'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'street'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'city'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;]));&lt;/span&gt;

&lt;span class="nv"&gt;$errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;structured&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// reject, retry, or ask for a correction&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provider-enforced structured output reduces risk, but it does not make generated content trusted. Validate the shape you receive, and handle generated values as carefully as any user-supplied input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wider provider coverage
&lt;/h2&gt;

&lt;p&gt;Prisma 0.5 now covers 29 providers across text, image, audio, and video workflows. The release adds Azure OpenAI text support, VertexAI text support, image generation through xAI, ModelsLab, and Replicate, and text embeddings across more providers.&lt;/p&gt;

&lt;p&gt;OpenAI-compatible endpoints remain a practical escape hatch. Local servers, internal gateways, and proxy services can be used through the &lt;code&gt;openai&lt;/code&gt; provider by changing the base URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GATEWAY_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'https://my-gateway.example.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'my-model'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from an OpenAI-compatible gateway'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provider tools also behave more carefully in 0.5. Prisma can omit unsupported combinations, such as a server-side tool that a provider cannot use for the current request shape, without forcing every application to know those edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability where the call happens
&lt;/h2&gt;

&lt;p&gt;Production AI calls need accounting. A plain response string cannot tell you which model ran, how long the request took, whether it failed, or what usage the provider reported.&lt;/p&gt;

&lt;p&gt;Prisma 0.5 adds request-scoped observers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Values\Observation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Observation&lt;/span&gt; &lt;span class="nv"&gt;$observation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ai.operation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$observation&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gpt-4.1-mini'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Draft a changelog entry'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An observation records the operation, provider type, provider name, model, duration, error state, usage, and metadata. Streamed responses are observed after the stream completes, so their usage and metadata are present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage and metadata now have names
&lt;/h2&gt;

&lt;p&gt;Provider usage payloads are inconsistent. &lt;code&gt;input_tokens&lt;/code&gt;, &lt;code&gt;prompt_tokens&lt;/code&gt;, &lt;code&gt;promptTokenCount&lt;/code&gt;, and &lt;code&gt;inputTokens&lt;/code&gt; may all mean the same thing, depending on which API answered.&lt;/p&gt;

&lt;p&gt;In 0.5, &lt;code&gt;usage()&lt;/code&gt; returns a &lt;code&gt;Values\Usage&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;promptTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;completionTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;totalTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;cacheReadTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;cacheWriteTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;thoughtTokens&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$usage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;used&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;meta()&lt;/code&gt; returns a &lt;code&gt;Values\Meta&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$meta&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$meta&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$meta&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;thinking&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$meta&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;reasoningDetails&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both objects remain array-compatible for provider-specific fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$rawUsage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'created'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Existing code that type-hints these results as arrays should switch to &lt;code&gt;Values\Usage&lt;/code&gt;, &lt;code&gt;Values\Meta&lt;/code&gt;, or call &lt;code&gt;all()&lt;/code&gt; when a raw array is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing without a live provider
&lt;/h2&gt;

&lt;p&gt;Application tests should not need live API keys to prove that the right Prisma calls are made. Prisma 0.5 adds a recording fake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Prisma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aimeos\Prisma\Responses\TextResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$fake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nc"&gt;TextResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Invoice approved'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withUsage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prompt_tokens'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'completion_tokens'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Review this invoice'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$fake&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertCalled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'write'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'invoice'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For provider-level tests, the new testing helpers can run real provider code against mocked Guzzle responses. Request building, response parsing, streaming, and tool loops can be exercised without leaving the test process.&lt;/p&gt;

&lt;p&gt;Responses implement &lt;code&gt;JsonSerializable&lt;/code&gt;, which keeps snapshot-style assertions straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;jsonSerialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Safer response boundaries
&lt;/h2&gt;

&lt;p&gt;Provider responses may be streamed, proxied, malformed, or simply too large. &lt;code&gt;withMaxResponseSize()&lt;/code&gt; bounds how many bytes Prisma will read from a single provider response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openai'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'OPENAI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withMaxResponseSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Analyze this document'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default limit is 64 MB per provider response. It applies to streamed and non-streamed calls, including individual tool-loop turns.&lt;/p&gt;

&lt;p&gt;The release also tightens provider discovery by validating provider type and name before building provider class names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom providers are part of the story
&lt;/h2&gt;

&lt;p&gt;Prisma resolves providers by namespace convention:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Prisma&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myprovider'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That maps to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Aimeos\Prisma\Providers\Text\Myprovider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new &lt;a href="https://github.com/aimeos/prisma/blob/master/CUSTOM-PROVIDERS.md" rel="noopener noreferrer"&gt;custom provider guide&lt;/a&gt; documents provider discovery, contracts, response objects, structured output, tool loops, async operations, OpenAI-compatible APIs, and testing.&lt;/p&gt;

&lt;p&gt;That is useful when a project has an internal gateway, a private model host, or a provider that Prisma does not ship yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrading
&lt;/h2&gt;

&lt;p&gt;The main migration points are small but worth checking. Use &lt;code&gt;stream()&lt;/code&gt; for live text responses. Pass prior turns through &lt;code&gt;withMessages()&lt;/code&gt;. Call &lt;code&gt;structure()&lt;/code&gt; to request structured output; keep using &lt;code&gt;structured()&lt;/code&gt; to read the parsed response. Treat &lt;code&gt;usage()&lt;/code&gt; and &lt;code&gt;meta()&lt;/code&gt; as value objects, or call &lt;code&gt;all()&lt;/code&gt; when existing code expects arrays. Drain streamed responses before reading usage, metadata, citations, tool steps, or finish reason. Reset &lt;code&gt;Prisma::fake()&lt;/code&gt; in test teardown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Docs: &lt;a href="https://php-prisma.org" rel="noopener noreferrer"&gt;https://php-prisma.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/aimeos/prisma" rel="noopener noreferrer"&gt;https://github.com/aimeos/prisma&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Custom providers: &lt;a href="https://github.com/aimeos/prisma/blob/master/CUSTOM-PROVIDERS.md" rel="noopener noreferrer"&gt;CUSTOM-PROVIDERS.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prisma 0.4 established the broad interface across text, image, audio, and video. Prisma 0.5 makes that interface easier to run in production: streamed UIs, observable calls, cheaper tests, clearer schemas, provider fallbacks, and custom integrations.&lt;/p&gt;

</description>
      <category>php</category>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to implement a multi-vendor e-commerce marketplace using Laravel</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Thu, 25 Jun 2026 11:09:19 +0000</pubDate>
      <link>https://dev.to/aimeos/how-to-implement-a-multi-vendor-e-commerce-marketplace-397a</link>
      <guid>https://dev.to/aimeos/how-to-implement-a-multi-vendor-e-commerce-marketplace-397a</guid>
      <description>&lt;p&gt;A marketplace is a multi-tenant system that happens to sell things. That sentence is the whole implementation problem in one line. The seller dashboard looks like the hard part during planning, but the real work shows up around week three, when every query in the system suddenly has to answer a new question. Whose data is this? Which vendor owns this product, this order line, this stock level, this price? The storefront was never the issue. The issue is that a marketplace is multi-tenant from the first table, and most shops are not.&lt;/p&gt;

&lt;p&gt;So the first decision you make is also the one that costs the most if you get it wrong: do you build the tenancy yourself, or start from a backend that already has it. Retrofitting isolation onto a single-tenant shop is not a feature you add — it's a rewrite you discover. You thread a &lt;code&gt;vendor_id&lt;/code&gt; through models, then through queries, then through the cart, then through the admin, and every place you forget becomes a data leak where one seller sees another seller's orders. This guide takes the other path: build on Aimeos, a Laravel ecommerce package that's multi-tenant from the data model up, and spend your time on the marketplace instead of the plumbing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide where tenancy lives
&lt;/h2&gt;

&lt;p&gt;Before any code, pick the foundation honestly, because it determines how much of the next month you spend on isolation you'll never show a user.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Vendor isolation&lt;/th&gt;
&lt;th&gt;Self-service onboarding&lt;/th&gt;
&lt;th&gt;Scales to thousands of vendors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Build it yourself&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;you thread it through every query&lt;/td&gt;
&lt;td&gt;you build it&lt;/td&gt;
&lt;td&gt;you re-architect for it later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Single-tenant shop + add-on&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;bolted onto a single-tenant base&lt;/td&gt;
&lt;td&gt;extension-dependent&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Aimeos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;built into the data model, scoped per site&lt;/td&gt;
&lt;td&gt;one env flag&lt;/td&gt;
&lt;td&gt;designed for it, 1 to more than 1 billion items&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Build it yourself&lt;/strong&gt; looks cheapest on a whiteboard and turns out to be the most expensive. Tenancy is a cross-cutting concern: it touches every model, every join, every report and every API endpoint, and the cost isn't the scoping code you write — it's the one clause you forget. A single missing filter in a join is one vendor reading another's orders, and you find it in production, not review. It also never stays finished. Every feature you add afterwards has to re-earn its isolation, so you end up maintaining a multi-tenancy framework as an unpaid side project to the marketplace you actually wanted to build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-tenant shop + add-on&lt;/strong&gt; moves the problem rather than solving it. The base assumes one merchant, so the extension grafts vendor columns and filters onto a schema that was never designed for them. Isolation then lives in the add-on's discipline instead of the data layer — it holds where the extension remembered to apply it and leaks at the edges the base shop reaches directly: admin tools, exports, and third-party plugins that have never heard of vendors. On top of that you inherit the add-on's release cycle and price, and you're betting it keeps pace with the platform it's bolted to.&lt;/p&gt;

&lt;p&gt;The rest of this guide assumes the third row, where isolation is a property of the data model rather than something layered on top. Each step is a flag or a small amount of config, not a sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stand up the backend
&lt;/h2&gt;

&lt;p&gt;You need PHP 8.2+ and a database (MySQL, MariaDB, PostgreSQL or SQL Server). The distribution wires the storefront, the admin, the APIs and a seeded catalog in one command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project aimeos/aimeos myshop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer the prompts for database, mail and the admin account, then look around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;myshop
php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The storefront is at &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt;, the admin at &lt;code&gt;http://127.0.0.1:8000/admin&lt;/code&gt;. At this point you have a working single shop. The next two steps turn it into a marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable multi-vendor mode
&lt;/h2&gt;

&lt;p&gt;The multi-vendor machinery ships in the box. You switch it on with one line in &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOP_MULTISHOP=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives every vendor a scoped storefront and a scoped backend at their own &lt;em&gt;site&lt;/em&gt; — Aimeos's word for a tenant. You can see what the flag did in the routing: every route gains a &lt;code&gt;{site}&lt;/code&gt; segment, so the storefront, the JSON:API, the admin panels and the seller's own backend all scope to the vendor in the URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'admin/{site}/jqadm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'verified'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;span class="s1"&gt;'graphql'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'admin/{site}/graphql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'verified'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;span class="s1"&gt;'jsonapi'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{site}/jsonapi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'api'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;span class="s1"&gt;'default'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{site}/shop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;span class="s1"&gt;'supplier'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{site}/s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;{site}&lt;/code&gt; placeholder isn't there for pretty URLs. It's the seam that keeps one vendor's administration from reaching into another's, all the way down to the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let vendors onboard themselves
&lt;/h2&gt;

&lt;p&gt;Creating each seller account by hand doesn't scale past a demo. Turn on self-registration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOP_REGISTRATION=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A newly registered seller gets administrator rights over their own site and nothing else — their catalog, their orders, their customers, their settings, none of anyone else's. If that's more power than you want to hand a fresh signup, drop the default permission level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOP_PERMISSION=editor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if neither "admin" nor "editor" maps to the access you have in mind, the permission sets are themselves configuration. Publish your own version of the admin resource config and decide exactly which panels and actions each role can touch. The platform operator keeps the root; vendors get precisely the slice you grant them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understand the isolation you just got
&lt;/h2&gt;

&lt;p&gt;It's worth knowing why the two flags above are enough, so you trust the result instead of double-checking it forever. Aimeos organizes everything around the site. Every record the system stores — products, prices, orders, stock — carries a site id, and the data layer filters on it automatically. You never write the &lt;code&gt;where siteid = ?&lt;/code&gt; clause; the manager that loads the data already added it. That single design decision is what turns "build a marketplace" from a tenancy project back into a normal shop project.&lt;/p&gt;

&lt;p&gt;Sites form a tree rather than a flat list, so a parent can hold shared catalog, categories or configuration that child vendors inherit, while each vendor still owns and overrides their own. A platform operator runs the root; vendors live underneath it with their data sealed off from each other by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give each vendor a catalog and a storefront
&lt;/h2&gt;

&lt;p&gt;Each seller logs into a backend that looks like a complete shop because, scoped to their site, it is one. They manage their own products with the full Aimeos catalog model behind them — variants, bundles, vouchers, virtual and downloadable goods, configurable and custom products, and subscriptions with recurring payments. A marketplace rarely sells one shape of thing; the moment one vendor wants tiered B2B pricing while another sells monthly boxes and a third sells license keys, a thin product table becomes the bottleneck. Aimeos models all of it without schema surgery, so you don't have to say no to a seller's business model.&lt;/p&gt;

&lt;p&gt;On the storefront side, each vendor has a public supplier page (the &lt;code&gt;/s&lt;/code&gt; route from Step 2) — a branded presence inside the marketplace with their catalog, profile and listings. Buyers shop across vendors; the basket and checkout are shared; the data behind each line stays attributed to the vendor that owns it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handle the money
&lt;/h2&gt;

&lt;p&gt;This is the step teams put off and regret. The marketplace-specific concerns — routing the lines of a mixed-vendor order to the right sellers, commissions, and seller payouts — live in a dedicated &lt;a href="https://aimeos.com/extensions" rel="noopener noreferrer"&gt;marketplace extension&lt;/a&gt; that builds on the multi-vendor core. The core gives you isolation and per-vendor administration for free; the extension adds the commercial layer of running a platform that takes a cut.&lt;/p&gt;

&lt;p&gt;Settle the money at the gateway rather than reconciling it by hand afterward. Aimeos ships payment extensions built for marketplaces — Stripe among them — that split each transaction the moment it's captured, sending the platform its commission and forwarding the remainder to the seller who fulfilled the line. Payouts stop being a monthly spreadsheet exercise and become a property of checkout: the buyer pays once, and the money lands where it's owed, already divided. The same model covers the awkward cases a marketplace inherits — refunds that have to claw back the right share, and orders spanning several vendors that need several payees from a single basket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan for scale before you need it
&lt;/h2&gt;

&lt;p&gt;Marketplaces don't fail at launch. They fail when they succeed — when a few dozen vendors become a few thousand, each with thousands of SKUs, and the catalog that felt instant at 5,000 products crawls at five million. Scale is the requirement that's invisible on day one and existential by month eighteen.&lt;/p&gt;

&lt;p&gt;You don't implement anything extra here; you inherit it. Aimeos runs the same architecture from a single seller up past a billion items, with render times down to around 20ms and response times near 100ms on a properly built catalog. The performance work a hand-rolled marketplace postpones until it's an emergency is the work this backend already did, so growth stays a business problem instead of becoming a database firefight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go headless where it pays
&lt;/h2&gt;

&lt;p&gt;Vendors increasingly want their own tooling — a mobile app to manage listings, a custom analytics view, an ERP that pushes inventory. Aimeos is API-first underneath the bundled storefront: a JSON:API following jsonapi.org for the buyer side and a GraphQL API for administration, both already scoped per site. Drive the whole marketplace headless, give vendors programmatic access to their own data, or keep the included storefront and only go headless where it pays. None of those are a rebuild — they're the same backend addressed differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify it
&lt;/h2&gt;

&lt;p&gt;The claim worth testing is the boring one: that the isolation is real and you didn't have to write it. With &lt;code&gt;SHOP_MULTISHOP=true&lt;/code&gt; and &lt;code&gt;SHOP_REGISTRATION=true&lt;/code&gt; set, create a couple of vendor accounts, sign in as each, and confirm the obvious thing from the inside — neither one can see the other's catalog or orders, and nobody wrote a scoping clause to make that true.&lt;/p&gt;

&lt;p&gt;The live &lt;a href="https://laravel.demo.aimeos.org" rel="noopener noreferrer"&gt;frontend demo&lt;/a&gt; and &lt;a href="https://admin.demo.aimeos.org" rel="noopener noreferrer"&gt;admin demo&lt;/a&gt; are up if you want a look first, the &lt;a href="https://aimeos.org/docs/latest/laravel" rel="noopener noreferrer"&gt;docs&lt;/a&gt; cover the multi-vendor setup end to end, and the &lt;a href="https://aimeos.com/extensions" rel="noopener noreferrer"&gt;marketplace extension&lt;/a&gt; is where the commission and payout layer lives.&lt;/p&gt;

&lt;p&gt;Implementing a marketplace is mostly about not implementing the parts that should already exist. Start from a backend that's multi-tenant by design, and the thing you ship is the marketplace — not the plumbing underneath it.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>ecommerce</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PagibleAI: A CMS for your Laravel application</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Mon, 22 Jun 2026 12:15:09 +0000</pubDate>
      <link>https://dev.to/aimeos/pagibleai-a-cms-for-your-laravel-application-3mh4</link>
      <guid>https://dev.to/aimeos/pagibleai-a-cms-for-your-laravel-application-3mh4</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi13bdgno3bhgytko9e6e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi13bdgno3bhgytko9e6e.jpg" alt="Cover image" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add content management to a Laravel app you already run. Pagible is a Composer package that brings structured content, versioning, GraphQL and JSON:API, an AI editor, and an MCP server — without taking over your app.&lt;/p&gt;




&lt;p&gt;Every Laravel project hits the same question eventually. The client wants to edit the content themselves, and you have to decide who owns the application.&lt;/p&gt;

&lt;p&gt;None of the usual answers are clean.&lt;/p&gt;

&lt;p&gt;Run WordPress in headless mode and you take on a second runtime, a second auth system, and a REST API you didn't design. Adopt a hosted platform like Contentful and you pay per record while your content lives on someone else's servers. Build a bespoke admin panel and you spend the next two months rebuilding a tree editor, a media library, and a draft/publish flow instead of shipping the product.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What you take on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Headless WordPress&lt;/td&gt;
&lt;td&gt;A second runtime, a second auth system, a REST API you didn't design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted platform (Contentful)&lt;/td&gt;
&lt;td&gt;Per-record pricing, your content on someone else's servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bespoke admin panel&lt;/td&gt;
&lt;td&gt;Months rebuilding a tree editor, media library, and publish flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PagibleAI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One Composer package; your app stays yours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;PagibleAI&lt;/a&gt; starts from a different premise: add content management to a Laravel app you already run. You &lt;code&gt;composer require&lt;/code&gt; it, and your app stays your app. The CMS moves in as a set of packages, brings its own models, migrations, admin panel, and APIs, and stays out of the way the rest of the time.&lt;/p&gt;

&lt;p&gt;Here's what stands out from a developer's seat.&lt;/p&gt;

&lt;h2&gt;
  
  
  The install is a normal Composer package
&lt;/h2&gt;

&lt;p&gt;There's no service to host and nothing external to wire up. If you have a Laravel 11, 12, or 13 app on PHP 8.2+, you add the package and run the migrations. That's the whole install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/pagible
php artisan cms:install
php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then grant yourself editing rights:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan cms:user &lt;span class="nt"&gt;-e&lt;/span&gt; editor@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The admin panel is served from your own app at &lt;code&gt;/cmsadmin&lt;/code&gt;. It's a Vue 3 and Vuetify single-page app talking to a GraphQL endpoint. No external dashboard, no webhook round-trips, no second deployment to keep in sync.&lt;/p&gt;

&lt;p&gt;Underneath, it's a monorepo split into focused packages: core models, admin, AI, GraphQL, JSON:API, search, MCP, backup, import, and theming. They share the &lt;code&gt;Aimeos\Cms\&lt;/code&gt; namespace. You install one meta-package and get all of it, but each concern stays isolated, so the surface you have to reason about stays small.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it's built on
&lt;/h2&gt;

&lt;p&gt;There's not much exotic here. Each capability leans on a package the Laravel community already knows, so most of the stack is familiar before you read a line of Pagible's own code.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel/framework&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Laravel 11 / 12 / 13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nuwave/lighthouse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GraphQL admin API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel-json-api/laravel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON:API content delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel/scout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full-text search engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel/mcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MCP server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel/reverb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Real-time broadcasting (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;laravel/cashier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Payments and paywalls — Stripe, Paddle, Mollie (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aimeos/prisma&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Broad LLM provider integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aimeos/laravel-nestedset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optimized nested-set page tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;intervention/image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image processing and previews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;league/commonmark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Markdown rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ezyang/htmlpurifier&lt;/code&gt;, &lt;code&gt;enshrined/svg-sanitize&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Content sanitization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The admin panel is its own front end on top: Vue 3, Vuetify, and Vite, built into a bundle that ships with the package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content is structured, not a wall of HTML
&lt;/h2&gt;

&lt;p&gt;This is what sets Pagible apart from the WordPress lineage. A page isn't one big rich-text field. It's a node in a tree that holds an ordered list of typed content elements.&lt;/p&gt;

&lt;p&gt;Three models carry the weight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Page&lt;/strong&gt; — a node in a nested-set tree, with drag-and-drop reordering, UUIDs, and soft deletes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Element&lt;/strong&gt; — a content block with a &lt;code&gt;type&lt;/code&gt; and a &lt;code&gt;data&lt;/code&gt; payload. Pages reference their elements in order, and the same element can be shared across many pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File&lt;/strong&gt; — media, with AI-generated descriptions and automatically sized previews.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cms_pages  (nested-set tree)
└─ Page ─┬─ ordered elements ── cms_elements   typed, reusable blocks
         ├─ attached files   ── cms_files      media + AI descriptions
         └─ every change     ── cms_versions   immutable snapshots
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A content element is a small, typed structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'id'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'ByC2ze'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'group'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'main'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'data'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'## A heading\n\nSome **markdown** body copy.'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;type&lt;/code&gt; maps to a Blade partial in the theme. The entire renderer for a text element in e.g. theme/views/text.blade.php is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@markdown($data-&amp;gt;text ?? '')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get a generous set of ~30 content element types out of the box including:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Renders&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Markdown body copy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hero&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full-width banner with background media&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cards&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Grid of linked cards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image-text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image alongside text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pricing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pricing tables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;slideshow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image carousel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Syntax-highlighted snippets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;questions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FAQ accordion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Adding your own type means defining its data shape and writing the partial that renders it. You keep full control of the markup, and you can override any view or drop in your own components.&lt;/p&gt;

&lt;p&gt;One detail matters for security. The mapping from a type to its handler comes from a trusted schema keyed by the type name, never from the stored element data. A content author can't smuggle a different handler into a record's payload, which closes a whole class of injection problems before it starts.&lt;/p&gt;

&lt;p&gt;The payoff is the one Contentful built a business on. Your front end consumes predictable, typed data instead of parsing arbitrary HTML. The same content can render as a web page, feed a mobile app, or drive a sitemap, with no one copy-pasting markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two APIs, pointed in opposite directions
&lt;/h2&gt;

&lt;p&gt;Pagible is API-first in a literal sense. The admin panel is just one client of the API, not a privileged path into the database.&lt;/p&gt;

&lt;p&gt;Editing runs over &lt;strong&gt;GraphQL&lt;/strong&gt;, built on Lighthouse. It's the read-write surface the admin uses, and the same one your own tooling, scripts, or integrations can talk to.&lt;/p&gt;

&lt;p&gt;Delivery runs over a read-only &lt;strong&gt;JSON:API&lt;/strong&gt; that follows the spec, tuned for the public side. The split is deliberate. The write API can afford to be expressive; the read API is built to serve content fast and cache hard. Rendered pages are cached per-page with a configurable TTL, a day by default, so the common case never touches the editing machinery.&lt;/p&gt;

&lt;p&gt;Prefer to render server-side? The theme package ships Blade templates and small directives like &lt;code&gt;@markdown&lt;/code&gt; and &lt;code&gt;@localDate&lt;/code&gt;, and all of it is yours to override.&lt;/p&gt;

&lt;h2&gt;
  
  
  Versioning an editorial team can trust
&lt;/h2&gt;

&lt;p&gt;Every change to a page, element, or file becomes an immutable snapshot in &lt;code&gt;cms_versions&lt;/code&gt;. Editors see the latest draft. The public sees the most recently published version. Those are two different things, on purpose.&lt;/p&gt;

&lt;p&gt;That model gives you the workflow features for free:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save a draft without touching the live site.&lt;/li&gt;
&lt;li&gt;Schedule a version to go live later. &lt;code&gt;cms:publish&lt;/code&gt; promotes anything whose &lt;code&gt;publish_at&lt;/code&gt; has passed, on a schedule.&lt;/li&gt;
&lt;li&gt;Revert to any earlier snapshot when an edit goes wrong.&lt;/li&gt;
&lt;li&gt;Keep a bounded history (ten versions per item by default) as an audit trail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For teams, there's an unsaved-changes guard, concurrent-edit protection, and a Git-like three-way merge when two people touch the same content. A half-finished draft is never one stray click from production.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI is wired in per task, not bolted on as a chatbot
&lt;/h2&gt;

&lt;p&gt;The "AI" in PagibleAI isn't one assistant sitting in a corner. It's a set of content operations, each routed to whichever provider does that job best, configured by environment variable.&lt;/p&gt;

&lt;p&gt;The defaults look like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Write and refine copy, describe media&lt;/td&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate and edit images (inpaint, repaint)&lt;/td&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Translate&lt;/td&gt;
&lt;td&gt;DeepL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Erase, isolate background, uncrop, upscale&lt;/td&gt;
&lt;td&gt;Clipdrop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transcribe audio&lt;/td&gt;
&lt;td&gt;OpenAI Whisper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each task reads its own &lt;code&gt;CMS_AI_{TASK}&lt;/code&gt; / &lt;code&gt;_MODEL&lt;/code&gt; / &lt;code&gt;_API_KEY&lt;/code&gt; trio. You configure only the providers you use, and you can point any task at a different model or provider without touching code. There are batch commands too. &lt;code&gt;cms:description&lt;/code&gt;, for example, walks through pages and media that lack descriptions and writes SEO meta text and alt text for them.&lt;/p&gt;

&lt;p&gt;Translation is the standout. Content can be translated into more than 35 languages while keeping its structured shape intact, so a translated page is still a real page, not a flattened copy. The whole AI layer is there when you want it and out of the way when you don't — it's truly optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The MCP server is the genuinely new part
&lt;/h2&gt;

&lt;p&gt;This is where Pagible reads the room. The same operations the admin panel performs are exposed as &lt;a href="https://pagible.com/configure-mcp" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; tools — 33 of them, covering pages, elements, files, image editing, translation, and search.&lt;/p&gt;

&lt;p&gt;The result: an assistant like Claude can run the CMS the way an editor would. Not by scraping a UI or guessing at an undocumented API, but through typed tools with real authorization behind them.&lt;/p&gt;

&lt;p&gt;"Draft a pricing page from these bullet points, generate a hero image, translate it into German, and schedule it for Monday" stops being a feature request. It becomes a sequence of tool calls an agent makes against your content, with the same permission checks and versioning a human edit goes through.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The CMS turns into something an agent can operate, not just a UI a human clicks through.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It works because the architecture was structured-first from the start. When content is typed and the operations are explicit, an agent has something solid to act on. That's the upside of not storing everything as a wall of HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling, and the boring parts that matter
&lt;/h2&gt;

&lt;p&gt;The same install runs on a single SQLite file for a brochure site and on a database cluster for millions of pages. It's Octane-friendly and built for cloud-native deployment.&lt;/p&gt;

&lt;p&gt;Search reflects that range. A custom Laravel Scout engine speaks the native dialect of whatever database you're on: FTS5 on SQLite, &lt;code&gt;MATCH … AGAINST&lt;/code&gt; on MySQL, &lt;code&gt;tsvector&lt;/code&gt; on PostgreSQL, &lt;code&gt;CONTAINSTABLE&lt;/code&gt; on SQL Server. No separate search cluster for something the database already does.&lt;/p&gt;

&lt;p&gt;Multi-tenancy is single-database by design. Every model is scoped by a &lt;code&gt;tenant_id&lt;/code&gt; through a global Eloquent scope, resolved by the Laravel tenancy package you probably already use. Multi-domain routing is a config flag. Real-time collaboration is opt-in over Laravel Reverb, broadcasting compact, metadata-only events so two editors don't clobber each other.&lt;/p&gt;

&lt;p&gt;The security posture is the kind you'd rather inherit than assemble: user content sanitized through HTMLPurifier, CSP headers enforced, hCaptcha on forms, URL validation on submitted links, and rate limiting across the API.&lt;/p&gt;

&lt;p&gt;Migrating in? There's a WordPress importer that moves a site over with an Artisan command, plus per-tenant backup and restore with integrity checks.&lt;/p&gt;

&lt;p&gt;Want to charge for content? A separate &lt;code&gt;aimeos/pagible-cashier&lt;/code&gt; package wires Pagible into Laravel Cashier, so you can put pages behind a paywall or sell course access through Stripe, Paddle, or Mollie. Its installer prompts for a provider, writes the credentials, and adds the &lt;code&gt;Billable&lt;/code&gt; trait to your user model. Like the rest, it's opt-in — install it only if you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who it's for, and the honest caveats
&lt;/h2&gt;

&lt;p&gt;Pagible fits when you have a Laravel app and want the people who own the content to manage it without you handing over the codebase. The headless APIs, structured content, and MCP tooling make it a solid base for anything where content feeds more than one front end.&lt;/p&gt;

&lt;p&gt;Two things to weigh. It's young and moving fast, and the AI features need third-party API keys, which means accounts and may need a budget if you want the full set.&lt;/p&gt;

&lt;p&gt;It's MIT licensed, so you can use it in commercial work with no per-site fees and no lock-in.&lt;/p&gt;

&lt;p&gt;None of the caveats change the central pitch, which is the thing I keep coming back to: it installs &lt;em&gt;into&lt;/em&gt; your app instead of asking your app to live inside it. If you've ever lost a weekend to a headless WordPress proxy, that alone is worth the &lt;code&gt;composer require&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is PagibleAI?
&lt;/h3&gt;

&lt;p&gt;PagibleAI is an open-source content management system that installs directly into an existing Laravel application. It provides structured content, versioning, an admin panel, GraphQL, JSON:API, AI-assisted editing, search, and an MCP server without replacing your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which Laravel and PHP versions does PagibleAI support?
&lt;/h3&gt;

&lt;p&gt;PagibleAI supports Laravel 11, 12, and 13 on PHP 8.2 or newer. You install it as a Composer package, run its installer and migrations, and manage it through the Laravel application you already deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does PagibleAI take over my Laravel application?
&lt;/h3&gt;

&lt;p&gt;No. Your Laravel application continues to own its authentication, business logic, data, infrastructure, and deployment. PagibleAI adds CMS packages, models, migrations, APIs, and an admin panel inside that application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is PagibleAI a headless CMS?
&lt;/h3&gt;

&lt;p&gt;PagibleAI supports both headless and server-rendered websites. Public content is available through a read-only JSON:API, editing operations use GraphQL, and Laravel applications can render pages directly with Blade templates and CMS directives.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does PagibleAI store content?
&lt;/h3&gt;

&lt;p&gt;PagibleAI stores content as typed, structured elements rather than one large HTML document. Pages contain ordered elements such as text, heroes, cards, pricing tables, slideshows, code samples, and FAQ sections. Elements can also be reused across multiple pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I create custom content types?
&lt;/h3&gt;

&lt;p&gt;Yes. A custom content type consists of a defined data structure and a Blade partial that renders it. The application controls the resulting HTML, and existing views can be overridden with project-specific templates or components.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do drafts and publishing work?
&lt;/h3&gt;

&lt;p&gt;Every change to a page, element, or file creates an immutable version. Editors work on the latest draft while visitors continue to see the last published version. Earlier versions can be restored, and future versions can be scheduled for publication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are the AI features required?
&lt;/h3&gt;

&lt;p&gt;No. All AI features are optional. Writing, translation, transcription, image generation, background removal, and other operations can be configured separately, and you only need API credentials for the services you choose to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the PagibleAI MCP server do?
&lt;/h3&gt;

&lt;p&gt;The MCP server exposes typed content-management tools for pages, elements, files, search, translation, and media operations. Compatible assistants can use those tools to draft, update, translate, and schedule content while going through the same authorization and versioning rules as human editors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which databases does PagibleAI support?
&lt;/h3&gt;

&lt;p&gt;PagibleAI works with SQLite, MySQL, MariaDB, PostgreSQL, and SQL Server. Its search engine uses each database's native full-text capabilities, so a separate search service is not required for the standard setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does PagibleAI support multiple tenants and domains?
&lt;/h3&gt;

&lt;p&gt;Yes. CMS records are tenant-scoped in a shared database, and multi-domain routing can be enabled through configuration. This allows one Laravel installation to manage content for multiple tenants or websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can PagibleAI protect private or paid content?
&lt;/h3&gt;

&lt;p&gt;Yes. Pages and media can have access rules, and private files are delivered through protected routes. The optional Cashier integration adds paid access through Stripe, Paddle, or Mollie.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is PagibleAI different from WordPress or Contentful?
&lt;/h3&gt;

&lt;p&gt;Unlike headless WordPress, PagibleAI does not introduce a second application runtime or authentication system. Unlike a hosted CMS, it keeps content in infrastructure you control and has no per-record pricing. It is designed specifically for Laravel applications that need structured, reusable content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is PagibleAI free for commercial projects?
&lt;/h3&gt;

&lt;p&gt;Yes. PagibleAI is released under the MIT license and has no per-site licensing fees. Optional AI providers, payment processors, hosting, and other third-party services may still have their own usage costs.&lt;/p&gt;




&lt;p&gt;The code and docs are at &lt;a href="https://pagible.com" rel="noopener noreferrer"&gt;pagible.com&lt;/a&gt; and on &lt;a href="https://github.com/aimeos/pagible" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you try it, I'd like to hear which part of the workflow surprised you.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>cms</category>
      <category>ai</category>
    </item>
    <item>
      <title>A working Laravel shop in five minutes with Aimeos</title>
      <dc:creator>Aimeos</dc:creator>
      <pubDate>Thu, 18 Jun 2026 13:20:40 +0000</pubDate>
      <link>https://dev.to/aimeos/a-working-laravel-shop-in-five-minutes-with-aimeos-h0</link>
      <guid>https://dev.to/aimeos/a-working-laravel-shop-in-five-minutes-with-aimeos-h0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjglxep2ckpgzgs0is4zs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjglxep2ckpgzgs0is4zs.png" alt=" " width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding a shop to a Laravel app usually turns into a quarter of work. You pick a cart library, bolt on a payment gateway, build an admin panel nobody asked to build, then discover your product model can't handle variants, bundles or tier prices without a rewrite. The ecommerce part eats the schedule; the Laravel part was never the problem.&lt;/p&gt;

&lt;p&gt;Aimeos takes the opposite route. It's a Laravel package that brings the storefront, the admin backend, a JSON:API for the frontend, a GraphQL API for administration, and a product model built for variants, bundles, subscriptions and block pricing. You install it the way you install anything else in Laravel, and you have a running shop before your coffee is cold.&lt;/p&gt;

&lt;p&gt;Here's the part people don't believe until they run it: the full setup is about five minutes. Two paths, depending on whether you're starting fresh or extending an app you already have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path one: a standalone shop
&lt;/h2&gt;

&lt;p&gt;If you don't have an app yet, the distribution wires everything up for you. You need PHP 8.2+ and a database (MySQL, MariaDB, PostgreSQL or SQL Server).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project aimeos/aimeos myshop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During install it asks for your database credentials, your mail settings, and the email and password for the admin account. It runs the schema setup and seeds demo data as part of the same step, so when it finishes you have a populated catalog, not an empty shell.&lt;/p&gt;

&lt;p&gt;Start it with the built-in server to look around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;myshop
php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The storefront is at &lt;a href="http://127.0.0.1:8000" rel="noopener noreferrer"&gt;http://127.0.0.1:8000&lt;/a&gt; and the admin backend at &lt;a href="http://127.0.0.1:8000/admin" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/admin&lt;/a&gt;. Log in with the account you just created. Catalog, baskets, checkout, orders and the dashboard are already there.&lt;/p&gt;

&lt;p&gt;For hosting, point your vhost document root at &lt;code&gt;myshop/public/&lt;/code&gt; and set &lt;code&gt;APP_URL&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt; to your domain. That's the only deployment-specific change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path two: into an existing Laravel app
&lt;/h2&gt;

&lt;p&gt;Already have an app and want a shop inside it? Require the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require aimeos/aimeos-laravel:~2025.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Publish the config and assets, run the migration, and let Aimeos set up its tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;public
php artisan migrate
php artisan aimeos:setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Append &lt;code&gt;--option=setup/default/demo:1&lt;/code&gt; to &lt;code&gt;aimeos:setup&lt;/code&gt; if you want demo data to click through; leave it off in production.&lt;/p&gt;

&lt;p&gt;Create a superuser for the backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan aimeos:account &lt;span class="nt"&gt;--super&lt;/span&gt; you@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prompts for a password. The shop now lives under your app's routes, sharing the same Laravel session, auth and config. The frontend renders at &lt;code&gt;/&lt;/code&gt; and the admin at &lt;code&gt;/admin&lt;/code&gt;, alongside whatever your app already serves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually get
&lt;/h2&gt;

&lt;p&gt;The install is short because the package isn't a starting point you finish writing — it's the finished thing, built to be customized rather than completed. Out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A storefront with catalog filters, search, basket, multi-step checkout and customer accounts.&lt;/li&gt;
&lt;li&gt;A full admin backend with a dashboard for products, orders, customers, pricing and marketing.&lt;/li&gt;
&lt;li&gt;A JSON:API following jsonapi.org for the frontend, so you can drop the bundled views and drive it from React, Vue or a native app.&lt;/li&gt;
&lt;li&gt;A GraphQL API for administration if you'd rather manage data programmatically.&lt;/li&gt;
&lt;li&gt;A product model that handles variants, bundles, vouchers, virtual and configurable products, plus subscriptions with recurring payments and block/tier pricing — without schema surgery.&lt;/li&gt;
&lt;li&gt;Over 100 payment gateway integrations through Omnipay.&lt;/li&gt;
&lt;li&gt;Multi-language routing, multi-vendor and multi-warehouse support, translated into 30+ languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's designed to stay fast as the catalog grows, from a handful of products into the millions, which is the part that usually decides whether a shop survives its second year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing without forking
&lt;/h2&gt;

&lt;p&gt;Every layer is replaceable through Laravel's own conventions. Configuration lives in &lt;code&gt;config/shop.php&lt;/code&gt;. Templates are standard Blade views you override by copying them into &lt;code&gt;resources/views/vendor/shop/&lt;/code&gt;. Business logic sits in decorators you register in config, so you change behavior by wrapping it, not by editing vendor code that the next update would overwrite. Turn on multi-language routing, multi-vendor mode or self-registration for sellers with a single &lt;code&gt;.env&lt;/code&gt; flag each:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOP_MULTILOCALE=true
SHOP_MULTISHOP=true
SHOP_REGISTRATION=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The honest test is to run it yourself rather than take the word count on faith. &lt;code&gt;composer create-project aimeos/aimeos myshop&lt;/code&gt;, answer the prompts, &lt;code&gt;php artisan serve&lt;/code&gt;, and open the browser. If you want to see the result first, the &lt;a href="https://laravel.demo.aimeos.org" rel="noopener noreferrer"&gt;frontend demo&lt;/a&gt; and &lt;a href="https://admin.demo.aimeos.org" rel="noopener noreferrer"&gt;admin demo&lt;/a&gt; are live.&lt;/p&gt;

&lt;p&gt;Docs are at &lt;a href="https://aimeos.org/docs/latest/laravel" rel="noopener noreferrer"&gt;aimeos.org/docs/latest/laravel&lt;/a&gt;, and if you're building a headless or PWA frontend, the &lt;a href="https://github.com/aimeos/aimeos-headless" rel="noopener noreferrer"&gt;Aimeos headless distribution&lt;/a&gt; ships API-only with JWT auth already configured.&lt;/p&gt;

&lt;p&gt;Five minutes to a working shop. The rest of the quarter is yours to spend on the parts that make it yours.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>webdev</category>
      <category>php</category>
      <category>ecommerce</category>
    </item>
  </channel>
</rss>
