<?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: K B Zaman</title>
    <description>The latest articles on DEV Community by K B Zaman (@kbzaman2).</description>
    <link>https://dev.to/kbzaman2</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%2F551726%2F99328f81-e61e-4ced-bd40-133509960e1f.png</url>
      <title>DEV Community: K B Zaman</title>
      <link>https://dev.to/kbzaman2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kbzaman2"/>
    <language>en</language>
    <item>
      <title>The Fundamentals of AI Engineering - EP 01</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Wed, 19 Aug 2026 06:08:30 +0000</pubDate>
      <link>https://dev.to/kbzaman2/the-fundamentals-of-ai-engineering-ep-01-1949</link>
      <guid>https://dev.to/kbzaman2/the-fundamentals-of-ai-engineering-ep-01-1949</guid>
      <description>&lt;p&gt;&lt;strong&gt;AI Engineering&lt;/strong&gt; means using an existing AI model to add useful AI features to a real software application.&lt;/p&gt;

&lt;p&gt;Those features might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Summarize a support ticket&lt;/li&gt;
&lt;li&gt;Classify a customer review&lt;/li&gt;
&lt;li&gt;Recommend products&lt;/li&gt;
&lt;li&gt;Answer questions from company documents&lt;/li&gt;
&lt;li&gt;Help automate a workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need to build or train an AI model yourself. As a Laravel developer, your job is to connect a suitable model to the application and make the complete feature reliable.&lt;/p&gt;

&lt;p&gt;For example, an AI model can analyze a customer's interests and recommend products. However, Laravel still decides which data the model may receive, sends the instructions, validates the returned product IDs, and controls what the user ultimately sees.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A simple rule to remember:&lt;/strong&gt; The AI model can understand information and suggest an answer. Laravel remains responsible for permissions, validation, database operations, payments, calculations, and the final business decision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What AI Engineering Actually Includes
&lt;/h2&gt;

&lt;p&gt;Imagine an e-commerce application that recommends products based on browsing behavior. The AI model is only one component of that feature.&lt;/p&gt;

&lt;p&gt;The complete engineering problem includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selecting a model whose quality, latency, context window, and price fit the task&lt;/li&gt;
&lt;li&gt;Supplying only relevant and authorized user and product data&lt;/li&gt;
&lt;li&gt;Designing prompts as versioned application contracts&lt;/li&gt;
&lt;li&gt;Retrieving private or current information from a knowledge base&lt;/li&gt;
&lt;li&gt;Constraining model actions through small, permission-aware Laravel tools&lt;/li&gt;
&lt;li&gt;Requesting structured output and validating it&lt;/li&gt;
&lt;li&gt;Handling timeouts, retries, invalid responses, and provider failures&lt;/li&gt;
&lt;li&gt;Measuring token usage, latency, failure rate, and output quality&lt;/li&gt;
&lt;li&gt;Protecting user data and controlling cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calling an AI API is one implementation detail. &lt;strong&gt;AI Engineering&lt;/strong&gt; is everything required to make that API call useful and dependable inside a real product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Laravel App vs. AI-Powered Laravel App
&lt;/h2&gt;

&lt;p&gt;A traditional Laravel feature follows rules defined by the developer. Its behavior is deterministic: given the same database state, the code returns the same result.&lt;/p&gt;

&lt;p&gt;Consider a simple product recommendation query:&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;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Product&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;'category_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;preferred_category_id&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;orderByDesc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rating'&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;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule is clear: return the five highest-rated products from the user's preferred category.&lt;/p&gt;

&lt;p&gt;This approach is inexpensive, predictable, and easy to test. It is also limited to the assumptions explicitly encoded in the query.&lt;/p&gt;

&lt;p&gt;An AI-assisted version can evaluate signals that are harder to represent as one fixed rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recently viewed products&lt;/li&gt;
&lt;li&gt;Previous purchases&lt;/li&gt;
&lt;li&gt;Budget&lt;/li&gt;
&lt;li&gt;Stated preferences&lt;/li&gt;
&lt;li&gt;Product compatibility&lt;/li&gt;
&lt;li&gt;The intent behind the current request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The request lifecycle might look 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;User request
    ↓
Laravel authorizes the request and assembles context
    ↓
AI model ranks eligible product candidates
    ↓
Laravel validates IDs, stock, price, and policy
    ↓
Laravel returns trusted product records
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The context sent to the model could look 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;Recently viewed:
- iPhone 17
- AirPods
- MacBook Air

Previous purchases:
- iPhone case
- USB-C charger

Budget: $200

Return five relevant product IDs from the eligible catalog.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model analyzes the context and proposes relevant products. Laravel then verifies that those products exist, are visible to the user, are in stock, and comply with business rules.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI-powered does not mean AI-controlled.&lt;/strong&gt; Authentication, payments, permissions, inventory, database writes, and business-critical calculations should remain deterministic. The model may recommend an action; Laravel must decide whether that action is valid and allowed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Four Concepts Every Developer Should Know
&lt;/h2&gt;

&lt;p&gt;Most AI application architecture becomes easier to understand once four terms are separated: &lt;strong&gt;LLM&lt;/strong&gt;, &lt;strong&gt;provider&lt;/strong&gt;, &lt;strong&gt;model&lt;/strong&gt;, and &lt;strong&gt;prompt&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. LLM
&lt;/h3&gt;

&lt;p&gt;LLM stands for &lt;strong&gt;Large Language Model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a type of AI system trained to understand and generate language. Depending on its capabilities, an LLM can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answer questions&lt;/li&gt;
&lt;li&gt;Summarize text&lt;/li&gt;
&lt;li&gt;Classify content&lt;/li&gt;
&lt;li&gt;Translate content&lt;/li&gt;
&lt;li&gt;Extract information&lt;/li&gt;
&lt;li&gt;Generate code&lt;/li&gt;
&lt;li&gt;Reason over supplied context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An LLM is the underlying category of technology—not the company providing the API and not the specific model selected for a request.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Provider
&lt;/h3&gt;

&lt;p&gt;A provider is the company or service that hosts AI models and exposes them through an API.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenAI&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anthropic&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Gemini&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;A local or hosted &lt;strong&gt;Ollama&lt;/strong&gt; deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your Laravel application normally communicates with the provider's API. The provider handles the infrastructure required to execute the selected model.&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
    ↓
Provider API
    ↓
Selected model
    ↓
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Model
&lt;/h3&gt;

&lt;p&gt;A model is the specific AI model that processes a request.&lt;/p&gt;

&lt;p&gt;One provider may offer several models optimized for different priorities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Provider
├── Model A → inexpensive and fast
├── Model B → balanced
└── Model C → advanced reasoning
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Models may differ in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reasoning quality&lt;/li&gt;
&lt;li&gt;Response speed&lt;/li&gt;
&lt;li&gt;Context-window size&lt;/li&gt;
&lt;li&gt;Supported modalities&lt;/li&gt;
&lt;li&gt;Tool-calling ability&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Token cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most powerful model is not automatically the correct model. The right choice depends on the task.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Prompt
&lt;/h3&gt;

&lt;p&gt;A prompt is the instruction and input sent to the model.&lt;/p&gt;

&lt;p&gt;A simple prompt might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain Laravel middleware.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production prompt normally has more structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a customer-support classification service.

Classify the message as positive, negative, or neutral.
Return JSON with: sentiment, category, and priority.

Message:
"The product is good, but delivery was very late."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prompt defines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The model's role&lt;/li&gt;
&lt;li&gt;The task&lt;/li&gt;
&lt;li&gt;The input data&lt;/li&gt;
&lt;li&gt;The expected output format&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The complete flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prompt
    ↓
Laravel selects a provider and model
    ↓
Provider executes the model
    ↓
LLM processes the supplied context
    ↓
Laravel parses and validates the response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Laravel AI Ecosystem
&lt;/h2&gt;

&lt;p&gt;The Laravel AI ecosystem is broader than an HTTP client for a model API. It includes the integration layers, providers, agents, tools, schemas, retrieval systems, protocols, queues, and operational controls required to ship AI features inside a Laravel application.&lt;/p&gt;

&lt;p&gt;Laravel provides official packages for two important sides of this ecosystem:&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;# Build AI-powered application features&lt;/span&gt;
composer require laravel/ai

&lt;span class="c"&gt;# Expose Laravel capabilities through an MCP server&lt;/span&gt;
composer require laravel/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI SDK helps Laravel consume models and build AI-powered application features. The MCP package helps Laravel expose carefully controlled application capabilities to AI clients.&lt;/p&gt;

&lt;p&gt;Seven building blocks appear repeatedly in production systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. AI Integration Layer
&lt;/h3&gt;

&lt;p&gt;An application-facing abstraction allows Laravel to work with providers and models without spreading raw, provider-specific HTTP requests throughout controllers and services.&lt;/p&gt;

&lt;p&gt;Provider credentials stay in configuration. Domain services own the use case and its business rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Providers and Models
&lt;/h3&gt;

&lt;p&gt;The application chooses a provider and model according to the quality, speed, context capacity, reliability, and cost required by the task.&lt;/p&gt;

&lt;p&gt;A small classification feature may use a fast, inexpensive model. A complex planning workflow may require stronger reasoning. Model selection is an engineering decision, not a branding decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Agents
&lt;/h3&gt;

&lt;p&gt;An agent is an AI-powered worker with a defined responsibility.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CustomerSupportAgent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ProductRecommendationAgent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InvoiceAnalysisAgent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TravelAssistantAgent&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An agent commonly combines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Instructions
    +
Context
    +
Tools
    ↓
Agent execution loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent is more than a single prompt call. It can inspect context, select an appropriate tool, observe the result, and continue until it can produce an answer or reach a defined limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Tools and Function Calling
&lt;/h3&gt;

&lt;p&gt;Models should not receive unrestricted access to your database or internal services.&lt;/p&gt;

&lt;p&gt;Instead, the model can request small, controlled Laravel tools such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getCustomerOrders()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;checkProductStock()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;calculateShipping()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createSupportTicket()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: "Show my last five orders"
    ↓
Agent selects getCustomerOrders
    ↓
Laravel tool validates identity and arguments
    ↓
Domain service runs an authorized query
    ↓
Agent explains the returned records
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model decides which tool may help. &lt;strong&gt;Laravel validates and performs the actual operation.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Structured Output
&lt;/h3&gt;

&lt;p&gt;Natural-language answers are useful for people but fragile for application logic.&lt;/p&gt;

&lt;p&gt;When software depends on the result, request a predictable structure:&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;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"negative"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delivery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&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;Laravel can validate this object before using it.&lt;/p&gt;

&lt;p&gt;Validation should reject:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing fields&lt;/li&gt;
&lt;li&gt;Unknown enum values&lt;/li&gt;
&lt;li&gt;Incorrect data types&lt;/li&gt;
&lt;li&gt;Nonexistent IDs&lt;/li&gt;
&lt;li&gt;Unauthorized resources&lt;/li&gt;
&lt;li&gt;Values outside domain limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A schema does not make the model infallible. It creates a contract that your application can enforce.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Embeddings and RAG
&lt;/h3&gt;

&lt;p&gt;An AI model does not automatically know your private documentation, and its training data may be outdated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;, or &lt;strong&gt;RAG&lt;/strong&gt;, searches your own knowledge base first and places the most relevant information into the model's prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Documents
    ↓
Embeddings
    ↓
Vector search
    ↓
Relevant passages
    ↓
Question + retrieved evidence
    ↓
LLM-generated answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Embeddings convert semantic meaning into numerical vectors. Vector search uses those vectors to find passages that are conceptually related to the user's question.&lt;/p&gt;

&lt;p&gt;Good RAG requires more than a vector database. It depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document quality&lt;/li&gt;
&lt;li&gt;Chunking strategy&lt;/li&gt;
&lt;li&gt;Metadata filters&lt;/li&gt;
&lt;li&gt;Access control&lt;/li&gt;
&lt;li&gt;Retrieval evaluation&lt;/li&gt;
&lt;li&gt;Clear citations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The database is infrastructure. Trustworthy answers come from the complete retrieval design.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Model Context Protocol
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MCP&lt;/strong&gt; stands for &lt;strong&gt;Model Context Protocol&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It standardizes how AI clients discover and use external tools and data sources.&lt;/p&gt;

&lt;p&gt;A Laravel MCP server can expose carefully designed capabilities such as orders, users, and reports without requiring a custom integration for every AI client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI client
    ↓
Model Context Protocol
    ↓
Laravel MCP server
    ↓
Authentication and authorization
    ↓
Orders, users, reports, and domain services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The ecosystem in one sentence:&lt;/strong&gt; Laravel AI Engineering is not simply calling an OpenAI endpoint. It combines model integration, agents, controlled tools, structured output, retrieval, validation, security, cost management, and standardized protocols according to the needs of the product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Agents and Controlled Tool Calling
&lt;/h2&gt;

&lt;p&gt;An agent should have a narrow responsibility and only the capabilities required for that responsibility.&lt;/p&gt;

&lt;p&gt;Follow these rules when exposing Laravel tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Give each tool one clear responsibility.&lt;/li&gt;
&lt;li&gt;Derive user identity from the authenticated request—never from model-supplied arguments.&lt;/li&gt;
&lt;li&gt;Validate every argument as rigorously as a public API request.&lt;/li&gt;
&lt;li&gt;Require explicit confirmation for destructive or financially meaningful actions.&lt;/li&gt;
&lt;li&gt;Log tool selection, inputs, results, duration, and authorization decisions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model can choose a tool, but it must never be able to bypass your application's policies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured Output Turns Language into Application Data
&lt;/h2&gt;

&lt;p&gt;Suppose an AI feature classifies customer messages. Returning a paragraph makes the result difficult for application code to consume. Returning a validated object makes the result useful.&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;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"negative"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delivery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&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;Laravel can now route the message to the delivery team, mark its priority, and store the classification.&lt;/p&gt;

&lt;p&gt;However, syntactically valid JSON can still contain an invalid business decision. Always validate both the structure and the meaning of the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embeddings, Vector Search, and RAG
&lt;/h2&gt;

&lt;p&gt;RAG is useful when the answer should come from information that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Private&lt;/li&gt;
&lt;li&gt;Frequently updated&lt;/li&gt;
&lt;li&gt;Specific to your organization&lt;/li&gt;
&lt;li&gt;Too large to place entirely in one prompt&lt;/li&gt;
&lt;li&gt;Required to include evidence or citations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A typical RAG pipeline works 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;Policies, guides, tickets, and product data
    ↓
Split into searchable chunks
    ↓
Generate embeddings
    ↓
Store vectors with metadata
    ↓
Search using the user's question
    ↓
Filter by permissions and relevance
    ↓
Place selected evidence in the prompt
    ↓
Generate an answer with source references
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not allow retrieval to bypass authorization. A document the current user cannot open should not appear in the model's context either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where MCP Fits
&lt;/h2&gt;

&lt;p&gt;MCP becomes useful when several AI clients need to discover and use the same Laravel capabilities.&lt;/p&gt;

&lt;p&gt;Without a protocol, each client may need its own custom integration. With MCP, Laravel can expose tools and resources through a shared contract while keeping authentication, authorization, validation, logging, and domain logic on the server.&lt;/p&gt;

&lt;p&gt;MCP does not remove the need for application security. It standardizes communication; Laravel still controls what each client and user may do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Production Engineering Checklist
&lt;/h2&gt;

&lt;p&gt;A feature is not production-ready because it worked in a demo.&lt;/p&gt;

&lt;p&gt;Before release, define how the system behaves across quality, reliability, security, cost, latency, and operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create representative test cases.&lt;/li&gt;
&lt;li&gt;Define explicit acceptance criteria.&lt;/li&gt;
&lt;li&gt;Evaluate outputs instead of relying on a few successful examples.&lt;/li&gt;
&lt;li&gt;Keep prompt and model versions attached to evaluation results.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reliability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set request timeouts.&lt;/li&gt;
&lt;li&gt;Use limited retries with backoff.&lt;/li&gt;
&lt;li&gt;Add circuit breakers for provider failures.&lt;/li&gt;
&lt;li&gt;Make tool execution idempotent where necessary.&lt;/li&gt;
&lt;li&gt;Move long-running work to queues.&lt;/li&gt;
&lt;li&gt;Provide a useful fallback.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Minimize the data sent to the model.&lt;/li&gt;
&lt;li&gt;Defend against prompt injection.&lt;/li&gt;
&lt;li&gt;Authorize every tool invocation.&lt;/li&gt;
&lt;li&gt;Keep secrets out of prompts and logs.&lt;/li&gt;
&lt;li&gt;Audit sensitive operations.&lt;/li&gt;
&lt;li&gt;Require confirmation for high-impact actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limit unnecessary context.&lt;/li&gt;
&lt;li&gt;Select the smallest model capable of the task.&lt;/li&gt;
&lt;li&gt;Cache safe, reusable results.&lt;/li&gt;
&lt;li&gt;Track token usage by feature and customer.&lt;/li&gt;
&lt;li&gt;Set budgets and usage limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Latency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stream user-facing text when appropriate.&lt;/li&gt;
&lt;li&gt;Move slow processing to background jobs.&lt;/li&gt;
&lt;li&gt;Avoid sending irrelevant context.&lt;/li&gt;
&lt;li&gt;Measure time spent in retrieval, model execution, and tools separately.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability
&lt;/h3&gt;

&lt;p&gt;Record enough information to understand failures and improve quality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt version&lt;/li&gt;
&lt;li&gt;Provider and model&lt;/li&gt;
&lt;li&gt;Token usage&lt;/li&gt;
&lt;li&gt;Response latency&lt;/li&gt;
&lt;li&gt;Tool calls&lt;/li&gt;
&lt;li&gt;Validation failures&lt;/li&gt;
&lt;li&gt;Retry count&lt;/li&gt;
&lt;li&gt;User feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A practical mental model:&lt;/strong&gt; Treat model output like input from an intelligent but untrusted external service—useful, sometimes surprising, and always subject to validation and policy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A Sensible First Architecture
&lt;/h2&gt;

&lt;p&gt;Start with one narrow and measurable use case.&lt;/p&gt;

&lt;p&gt;Do not begin with a general-purpose autonomous agent. Begin with a feature whose input, output, success criteria, and fallback you can clearly define.&lt;/p&gt;

&lt;p&gt;A production-minded request lifecycle looks 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;Authorize
Confirm identity and permissions
    ↓
Prepare
Retrieve and minimize context
    ↓
Generate
Call the selected model
    ↓
Validate
Enforce schema and business rules
    ↓
Observe
Record cost, latency, and quality signals
    ↓
Respond
Return the result or a deterministic fallback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A practical first implementation should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Place provider calls behind a domain service.&lt;/li&gt;
&lt;li&gt;Use a versioned prompt.&lt;/li&gt;
&lt;li&gt;Request a structured response.&lt;/li&gt;
&lt;li&gt;Validate the response and its business meaning.&lt;/li&gt;
&lt;li&gt;Log operational metadata.&lt;/li&gt;
&lt;li&gt;Provide a non-AI fallback.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add agents, RAG, or MCP only when the use case genuinely requires them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The goal of &lt;strong&gt;AI Engineering&lt;/strong&gt; is not to put a model everywhere.&lt;/p&gt;

&lt;p&gt;It is to use probabilistic capability exactly where it creates value while surrounding it with deterministic software that users can trust. That boundary is where strong Laravel engineering becomes an advantage.&lt;/p&gt;

&lt;p&gt;This article establishes the vocabulary and architecture for the rest of this series. The next chapters will go deeper into the Laravel AI SDK, agents, prompts, structured output, reliability, model economics, RAG, MCP, security, and observability.&lt;/p&gt;




&lt;p&gt;If you found this useful, follow me for the next article in the &lt;strong&gt;AI Engineering with Laravel&lt;/strong&gt; series.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>Case Study: How I Built a Modular Laravel CMS with Addons, Themes &amp; Dynamic Loading</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Fri, 07 Aug 2026 15:14:40 +0000</pubDate>
      <link>https://dev.to/kbzaman2/case-study-how-i-built-a-modular-laravel-cms-with-addons-themes-dynamic-loading-pea</link>
      <guid>https://dev.to/kbzaman2/case-study-how-i-built-a-modular-laravel-cms-with-addons-themes-dynamic-loading-pea</guid>
      <description>&lt;p&gt;Most Laravel CMS projects start clean.&lt;/p&gt;

&lt;p&gt;Then you add a blog.&lt;/p&gt;

&lt;p&gt;Then a contact form.&lt;/p&gt;

&lt;p&gt;Then multilingual support, analytics, cookie consent, newsletter subscriptions, SEO settings, custom pages...&lt;/p&gt;

&lt;p&gt;Before long, the "core" knows about everything.&lt;/p&gt;

&lt;p&gt;I wanted to build the opposite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laravel Addon CMS&lt;/strong&gt; is an open-source CMS built with Laravel 12 where the core stays intentionally small, product features live inside installable addons, and themes completely own the public-facing website.&lt;/p&gt;

&lt;p&gt;Instead of starting every new project by copying the previous Laravel project, the idea is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build the website by composing reusable features rather than forking an existing codebase.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;I've seen the same pattern repeatedly in Laravel projects.&lt;/p&gt;

&lt;p&gt;A feature starts reusable, but eventually becomes tightly coupled to a specific project.&lt;/p&gt;

&lt;p&gt;A blog module gets mixed into the main application.&lt;/p&gt;

&lt;p&gt;A contact form gets rewritten.&lt;/p&gt;

&lt;p&gt;Theme sections become one-off Blade files.&lt;/p&gt;

&lt;p&gt;Analytics code gets scattered around layouts.&lt;/p&gt;

&lt;p&gt;Then a bug gets fixed in one project while five older projects continue running the previous version.&lt;/p&gt;

&lt;p&gt;The problem isn't necessarily Laravel.&lt;/p&gt;

&lt;p&gt;The problem is &lt;strong&gt;where we draw the boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Laravel Addon CMS, I decided on three major boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core
├── Shared CMS infrastructure
│
Addons
├── Product features
│
Themes
└── Website presentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core shouldn't need to know what features developers will build in the future.&lt;/p&gt;




&lt;h1&gt;
  
  
  What the Core Owns
&lt;/h1&gt;

&lt;p&gt;The CMS core handles the things almost every website needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin authentication&lt;/li&gt;
&lt;li&gt;Media management&lt;/li&gt;
&lt;li&gt;Pages&lt;/li&gt;
&lt;li&gt;SEO settings&lt;/li&gt;
&lt;li&gt;Database-backed settings&lt;/li&gt;
&lt;li&gt;Theme customization&lt;/li&gt;
&lt;li&gt;Addon installation&lt;/li&gt;
&lt;li&gt;Addon lifecycle management&lt;/li&gt;
&lt;li&gt;File handling&lt;/li&gt;
&lt;li&gt;Shared helpers&lt;/li&gt;
&lt;li&gt;Dynamic addon/theme loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything outside that shared infrastructure can become an addon or part of a theme.&lt;/p&gt;

&lt;p&gt;The project currently uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laravel 12
PHP 8.2+
MySQL
Blade
Composer
Vite
Bootstrap
Artisan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  The Interesting Part: The Database Decides What Laravel Loads
&lt;/h1&gt;

&lt;p&gt;This is probably the architectural decision I like most about the project.&lt;/p&gt;

&lt;p&gt;Normally, Laravel service providers are registered through application configuration.&lt;/p&gt;

&lt;p&gt;But if an addon can be installed, enabled, disabled, or removed through the admin panel, I don't want developers manually editing configuration every time.&lt;/p&gt;

&lt;p&gt;So after installation, the application reads the active addons from the database.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application boots
      ↓
Check CMS tables
      ↓
Read active addons
      ↓
Find addon ServiceProviders
      ↓
Register providers
      ↓
Read active theme
      ↓
Register theme ServiceProvider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Addons live here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
└── Addons/
    ├── PostCraft/
    ├── MailMate/
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Themes live here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
└── Themes/
    ├── Brixly/
    ├── YourTheme/
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means enabling an addon isn't just changing a boolean that the UI checks.&lt;/p&gt;

&lt;p&gt;It changes what Laravel actually boots.&lt;/p&gt;

&lt;p&gt;The addon provider can determine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which routes exist&lt;/li&gt;
&lt;li&gt;Which controllers become available&lt;/li&gt;
&lt;li&gt;Which views are registered&lt;/li&gt;
&lt;li&gt;Which sidebar items appear&lt;/li&gt;
&lt;li&gt;Which frontend sections become available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same idea applies to themes.&lt;/p&gt;

&lt;p&gt;Switch the active theme and its provider becomes responsible for registering the public website.&lt;/p&gt;




&lt;h1&gt;
  
  
  An Addon Is Basically a Laravel Feature Package
&lt;/h1&gt;

&lt;p&gt;I deliberately avoided creating an entirely new framework developers would have to learn.&lt;/p&gt;

&lt;p&gt;If you know Laravel, the structure should already feel familiar.&lt;/p&gt;

&lt;p&gt;A typical addon can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Addons/Blog/
├── BlogServiceProvider.php
├── Activator.php
├── composer.json
├── routes/
├── controllers/
├── models/
├── views/
├── assets/
└── database/
    └── migrations/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each addon owns its feature.&lt;/p&gt;

&lt;p&gt;That means routes, controllers, models, migrations and views don't have to leak into the main application.&lt;/p&gt;




&lt;h1&gt;
  
  
  Scaffolding an Addon
&lt;/h1&gt;

&lt;p&gt;I also wanted addon development to feel similar to normal Laravel development.&lt;/p&gt;

&lt;p&gt;The project uses the &lt;code&gt;cmsaddoncommands&lt;/code&gt; package to provide Artisan commands for scaffolding.&lt;/p&gt;

&lt;p&gt;For example:&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;# Create the addon&lt;/span&gt;
php artisan make:addon Blog

&lt;span class="c"&gt;# Create an addon model&lt;/span&gt;
php artisan addon:model Blog Post &lt;span class="nt"&gt;-m&lt;/span&gt;

&lt;span class="c"&gt;# Create a controller&lt;/span&gt;
php artisan addon:controller Blog PostController

&lt;span class="c"&gt;# Create an addon migration&lt;/span&gt;
php artisan addon:migration Blog create_posts_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Addon migrations can also be handled independently:&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 addon:migrate Blog

php artisan addon:migrate:rollback Blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps database changes attached to the feature that owns them.&lt;/p&gt;




&lt;h1&gt;
  
  
  Registering Routes, Views and Admin Navigation
&lt;/h1&gt;

&lt;p&gt;An addon ServiceProvider can look something like this:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Addons\Blog&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\Lib\Sidenav&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\ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogServiceProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ServiceProvider&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;boot&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadRoutesFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/routes/cms_blog.php'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadViewsFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/views'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Blog'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Sidenav&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'Content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Blog posts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'admin.blog.index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'ph ph-article'&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;Nothing particularly magical is happening here.&lt;/p&gt;

&lt;p&gt;And that's intentional.&lt;/p&gt;

&lt;p&gt;It's still Laravel.&lt;/p&gt;

&lt;p&gt;The CMS mainly provides conventions and lifecycle management around familiar Laravel concepts.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addon Lifecycle Management
&lt;/h1&gt;

&lt;p&gt;Installable addons create another problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens to their database structure when they're activated or removed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each addon can provide an &lt;code&gt;Activator&lt;/code&gt; class with lifecycle hooks for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;activate
deactivate
delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During activation, the CMS can run migrations belonging specifically to that addon before marking it active.&lt;/p&gt;

&lt;p&gt;During deletion, it can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Roll back addon migrations.&lt;/li&gt;
&lt;li&gt;Execute the addon delete hook.&lt;/li&gt;
&lt;li&gt;Remove its files.&lt;/li&gt;
&lt;li&gt;Remove its database record.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The lifecycle stays intentionally simple.&lt;/p&gt;

&lt;p&gt;Laravel developers already understand migrations and Artisan, so I didn't want another abstraction hiding them.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addon Metadata and Dependencies
&lt;/h1&gt;

&lt;p&gt;Each addon also contains metadata describing itself.&lt;/p&gt;

&lt;p&gt;When distributing an addon, things like its nickname, version and dependencies matter.&lt;/p&gt;

&lt;p&gt;For example, an addon may declare:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;required_addons
required_system_version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few conventions I try to keep strict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addon nickname should match its folder/provider naming.&lt;/li&gt;
&lt;li&gt;Database changes belong inside the addon.&lt;/li&gt;
&lt;li&gt;Addons should use their own view namespaces.&lt;/li&gt;
&lt;li&gt;Dependencies should be declared before distribution.&lt;/li&gt;
&lt;li&gt;Lifecycle hooks should only handle work migrations can't handle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These restrictions make addons easier to move between projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  Themes Are More Than Blade Templates
&lt;/h1&gt;

&lt;p&gt;I didn't want themes to mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Change a CSS file and replace some Blade templates."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A theme should own the actual website presentation.&lt;/p&gt;

&lt;p&gt;A theme can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Themes/YourTheme/
├── YourThemeServiceProvider.php
├── routes/
├── controllers/
├── Lib/
├── views/
│   ├── layouts/
│   ├── sections/
│   └── slices/
├── assets/
├── config.json
└── screenshot.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting directory here is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;It contains the definitions for configurable website sections.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building Configurable Theme Sections
&lt;/h1&gt;

&lt;p&gt;Imagine a theme has a hero section.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding its content into Blade, the theme can describe the fields that should be editable.&lt;/p&gt;

&lt;p&gt;For example:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Themes\YourTheme\Lib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HeroSection&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;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSection&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'pages'&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;'home'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'position'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&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="s1"&gt;'Hero Section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&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;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'heading'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Heading'&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="s1"&gt;'Build something useful'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&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;'image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hero Image'&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="s1"&gt;'1200x800'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'accept'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'.png,.jpg,.jpeg,.webp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&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;'url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'button_url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Button URL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'attr'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'href'&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="s1"&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;Now the CMS understands that the section contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Heading → text
Image   → image
Button  → URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The admin customizer can generate editing controls from those definitions.&lt;/p&gt;




&lt;h1&gt;
  
  
  Rendering the Section
&lt;/h1&gt;

&lt;p&gt;The corresponding Blade file might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section class="hero-section"&amp;gt;
    &amp;lt;div class="container"&amp;gt;

        &amp;lt;div class="hero-content"&amp;gt;
            &amp;lt;h1&amp;gt;
                &amp;lt;x-ui.text
                    section="hero_section"
                    key="heading"
                /&amp;gt;
            &amp;lt;/h1&amp;gt;

            &amp;lt;x-ui.a
                class="btn"
                section="hero_section"
                key="button_url"
            &amp;gt;
                Learn more
            &amp;lt;/x-ui.a&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;x-ui.img
            class="img-fluid"
            section="hero_section"
            key="image"
            alt="Hero image"
        /&amp;gt;

    &amp;lt;/div&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These components resolve the saved theme content while preserving the editing hooks required by the CMS customizer.&lt;/p&gt;

&lt;p&gt;So the flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Section PHP class
        ↓
Defines editable fields
        ↓
Admin customizer
        ↓
User edits content
        ↓
Content stored as JSON
        ↓
Blade UI components
        ↓
Public website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives theme developers control over presentation without requiring site owners to edit Blade.&lt;/p&gt;




&lt;h1&gt;
  
  
  Repeaters and Dynamic Content
&lt;/h1&gt;

&lt;p&gt;Some sections aren't simple fields.&lt;/p&gt;

&lt;p&gt;Think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testimonials&lt;/li&gt;
&lt;li&gt;Client logos&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Team members&lt;/li&gt;
&lt;li&gt;Pricing cards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These need repeatable groups.&lt;/p&gt;

&lt;p&gt;The theme API therefore supports repeater definitions, while their frontend templates can live under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;views/slices/{section_key}/{repeater_key}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The theme controls how repeated items look, while the CMS controls how their content is edited and stored.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addons Can Also Push Frontend Sections
&lt;/h1&gt;

&lt;p&gt;This was another important requirement.&lt;/p&gt;

&lt;p&gt;Suppose I create a newsletter addon.&lt;/p&gt;

&lt;p&gt;The addon shouldn't only provide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/admin/subscribers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might also provide a reusable newsletter signup section.&lt;/p&gt;

&lt;p&gt;That section could then be inserted into a supported theme page.&lt;/p&gt;

&lt;p&gt;This lets feature addons participate in the frontend without owning the entire theme.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MailMate Addon
│
├── Subscriber management
├── Newsletter logic
└── Newsletter section
          ↓
       Theme page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The feature remains owned by the addon while presentation remains compatible with the theme system.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Service Providers Were the Right Boundary
&lt;/h1&gt;

&lt;p&gt;I considered creating a more custom module-loading system.&lt;/p&gt;

&lt;p&gt;But Laravel already has a good extension boundary:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Providers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They can register:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routes&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;li&gt;Bindings&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;Boot logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So rather than hiding Laravel, the CMS uses Laravel itself as much as possible.&lt;/p&gt;

&lt;p&gt;That's an architectural principle I've tried to maintain throughout the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add conventions around Laravel instead of replacing Laravel concepts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A developer shouldn't need to learn a private mini-framework just to build a CMS addon.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Trade-Off: Architecture Got More Attention Than UI
&lt;/h1&gt;

&lt;p&gt;One thing I'm very aware of is that the current UI/UX isn't the strongest part of the project.&lt;/p&gt;

&lt;p&gt;Most of the early work went into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addon boundaries&lt;/li&gt;
&lt;li&gt;Dynamic provider registration&lt;/li&gt;
&lt;li&gt;Theme registration&lt;/li&gt;
&lt;li&gt;Migration lifecycle&lt;/li&gt;
&lt;li&gt;Content configuration&lt;/li&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Developer tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That produced a system I'm happier extending, but it also means the admin interface still needs work.&lt;/p&gt;

&lt;p&gt;The customizer, media manager, addon management and theme controls could all be cleaner and more polished.&lt;/p&gt;

&lt;p&gt;I don't see that as an architectural problem.&lt;/p&gt;

&lt;p&gt;The foundation is there.&lt;/p&gt;

&lt;p&gt;The next stage is making that architecture pleasant for non-technical users too.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Would Keep
&lt;/h1&gt;

&lt;p&gt;If I rebuilt the project today, I would absolutely keep the separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core → infrastructure

Addons → features

Themes → presentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd also keep the Laravel-native approach.&lt;/p&gt;

&lt;p&gt;Service providers, Blade, migrations, route files, Composer metadata and Artisan commands are already familiar to Laravel developers.&lt;/p&gt;

&lt;p&gt;That's valuable.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Would Improve
&lt;/h1&gt;

&lt;p&gt;There are several things I'd invest more time in next.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Admin UI/UX
&lt;/h3&gt;

&lt;p&gt;The functionality exists, but workflows can be more intuitive and visually consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Automated Tests
&lt;/h3&gt;

&lt;p&gt;Especially around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install addon
Activate addon
Deactivate addon
Delete addon
Run migrations
Rollback migrations
Dependency validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These lifecycle operations deserve stronger automated coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Theme API Documentation
&lt;/h3&gt;

&lt;p&gt;The section system becomes much easier to use once you understand it, but that understanding shouldn't require reading the source.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Smaller Demo Data
&lt;/h3&gt;

&lt;p&gt;A smaller default installation would make the architecture easier for new contributors to explore.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Contributor Experience
&lt;/h3&gt;

&lt;p&gt;I'd like the path from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my first addon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to be extremely short.&lt;/p&gt;




&lt;h1&gt;
  
  
  It's Open Source
&lt;/h1&gt;

&lt;p&gt;Laravel Addon CMS is released under the &lt;strong&gt;MIT License&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm especially interested in contributions around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI/UX improvements&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Automated tests&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;li&gt;Bug fixes&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Theme sections&lt;/li&gt;
&lt;li&gt;New themes&lt;/li&gt;
&lt;li&gt;Focused addons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I prefer small, understandable pull requests over huge rewrites.&lt;/p&gt;

&lt;p&gt;One addon.&lt;/p&gt;

&lt;p&gt;One section.&lt;/p&gt;

&lt;p&gt;One admin workflow.&lt;/p&gt;

&lt;p&gt;One failing test.&lt;/p&gt;

&lt;p&gt;One documentation gap.&lt;/p&gt;

&lt;p&gt;Those improvements compound quickly in an extensible system.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;The biggest lesson from building this project wasn't how to create a CMS.&lt;/p&gt;

&lt;p&gt;It was about &lt;strong&gt;boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The difficult part of an extensible system isn't adding features.&lt;/p&gt;

&lt;p&gt;It's deciding what should &lt;strong&gt;not&lt;/strong&gt; know about those features.&lt;/p&gt;

&lt;p&gt;For Laravel Addon CMS, the answer became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The core provides infrastructure.
Addons provide capabilities.
Themes provide presentation.
The database decides what is active.
Laravel does the rest.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is still plenty to improve, especially around UI/UX, tests and documentation.&lt;/p&gt;

&lt;p&gt;But I think the architecture is moving in the right direction: a CMS where building the next Laravel website means assembling reusable pieces instead of copying the previous project.&lt;/p&gt;

&lt;p&gt;If you're a Laravel developer, I'd be interested to hear how you approach modularity in larger applications.&lt;/p&gt;

&lt;p&gt;Do you prefer packages, modules, domains, plugins—or something else?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; Laravel Addon CMS&lt;br&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Laravel 12, PHP, MySQL, Blade, Composer, Vite, Bootstrap&lt;br&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;br&gt;
&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/kbzaman76/laravel-cms" rel="noopener noreferrer"&gt;https://github.com/kbzaman76/laravel-cms&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally written from my experience designing and building Laravel Addon CMS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Content rewriting, editing, and formatting assistance provided by ChatGPT.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>No Code E-commerce APP Builder | BuildEcom</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Wed, 03 Sep 2025 06:25:37 +0000</pubDate>
      <link>https://dev.to/kbzaman2/no-code-e-commerce-app-builder-buildecom-3il6</link>
      <guid>https://dev.to/kbzaman2/no-code-e-commerce-app-builder-buildecom-3il6</guid>
      <description>&lt;h2&gt;
  
  
  Why mobile‑first matters for eCommerce
&lt;/h2&gt;

&lt;p&gt;Today’s shoppers live on their phones. &lt;strong&gt;Mobile commerce&lt;/strong&gt; is expected to account for more than half of all online sales worldwide and customers expect fast, app‑like experiences. Building a native mobile app from scratch usually requires &lt;strong&gt;thousands of dollars&lt;/strong&gt; and a &lt;strong&gt;team of developers&lt;/strong&gt;. That’s where no‑code platforms such as &lt;a href="https://buildecom.app/" rel="noopener noreferrer"&gt;BuildEcom&lt;/a&gt; come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is BuildEcom?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="//producthunt.com/products/buildecom#:~:text=Visit%20website"&gt;Product&amp;nbsp;Hunt&lt;/a&gt;, BuildEcom “lets you turn your online store into a mobile app in minutes” and helps merchants manage products, boost sales and reach more customers without touching code.&lt;/p&gt;

&lt;p&gt;It works as a bridge between your WordPress WooCommerce shop and the BuildEcom mobile app infrastructure. By installing the official &lt;a href="https://wordpress.org/plugins/buildecom/#:~:text=Description" rel="noopener noreferrer"&gt;WordPress plugin&lt;/a&gt; you can connect your store, enable push notifications through Firebase and provide mobile‑ready APIs&lt;/p&gt;

&lt;h2&gt;
  
  
  Drag‑and‑drop app builder
&lt;/h2&gt;

&lt;p&gt;Inside the BuildEcom platform you design your mobile app using a visual editor—no coding required. SourceForge notes that BuildEcom “is a no‑code app builder designed for WooCommerce stores” that lets you manage products, track orders and send push notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manage customers with notifications
&lt;/h2&gt;

&lt;p&gt;Push notifications are vital for re‑engaging mobile shoppers. BuildEcom uses Firebase Cloud Messaging to deliver order updates, promotions and abandoned‑cart reminders directly to the user’s device&lt;br&gt;
wordpress.org. Store owners can create custom notification templates from within WordPress and trigger them from WooCommerce events such as new orders or status changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Mobile commerce is no longer optional—it’s the default for many shoppers. BuildEcom makes it possible for WooCommerce merchants to join the mobile revolution without hiring developers or learning to code. By connecting your store through the BuildEcom plugin, customizing your app with a drag‑and‑drop builder and leveraging push notifications to drive engagement, you can launch a polished mobile app in days rather than months.&lt;/p&gt;

&lt;p&gt;If you’re ready to take your WooCommerce store to the next level, consider giving BuildEcom a try. With affordable pricing, cross‑platform support and a focus on usability, it could be the tool that helps you reach customers where they spend most of their time: on their phones.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Laravel Macroable Trait</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Fri, 05 Nov 2021 17:08:29 +0000</pubDate>
      <link>https://dev.to/kbzaman2/laravel-macroable-trait-85i</link>
      <guid>https://dev.to/kbzaman2/laravel-macroable-trait-85i</guid>
      <description>&lt;p&gt;Laravel is very popular with developers for its beautiful features. Macroable trait is one of its many beautiful features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definition in my language:
&lt;/h3&gt;

&lt;p&gt;Speaking of this trait, I would like to say that it is a virtual method maker of class. That means there is a class in your project where you want to call some methods dynamically, but those methods do not have any physical presence in that class. In that case, you can get help from Macroable Trait.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use:
&lt;/h3&gt;

&lt;p&gt;The first requirement to use this is to use the macroable trait in the class in which you want to create the macro. Then in the boot method of AppServiceProvider class, you have to write the code to create a macro of your class. A format of code is written below:&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;boot&lt;/span&gt; &lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nc"&gt;YourClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'methodName'&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="nv"&gt;$arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Your method body and your code&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;Suppose you think Laravel's Str class should have a method to connect two strings. But there is no such method in this class. Then you can create your own method for this class, without making any changes anywhere in this class. Because Laravel has some classes that use the Macroable trait by default. Among them Str class one. I will give the list of classes below. So how do we create a method in Str class to concat? You have already seen a demo format. That is the format we will use now.&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;boot&lt;/span&gt; &lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'concat'&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="nv"&gt;$str1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$str1&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$str2&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;Now if you write &lt;code&gt;$str = Str::concat('My String 1', 'My String 2');&lt;/code&gt;  then you will see that the two strings are connected. This means that a virtual method has been created in this class without any change in the Str class.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;When you call the macro method in a class Macroable, it enters the static macro method of the Macroable Trait. I mentioned the method below:&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$macro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$macros&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;It registers custom macros and stores them in its static macro property. Here comes the name of the custom method in the name variable and the instance of Closure in the macro variable.&lt;br&gt;
And when you call the custom method, the &lt;code&gt;__call()&lt;/code&gt; and &lt;code&gt;__callStatic()&lt;/code&gt; magic methods of Macroable Trait handle it dynamically.&lt;br&gt;
There is one more feature called mixin in Macroable Trait. I will try to talk about it in a later post InshaAllah.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>trait</category>
      <category>webdevs</category>
    </item>
  </channel>
</rss>
