<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">

<channel>
  
  <title><![CDATA[Manamil Dev]]></title>
  <link>https://manamil.dev</link>
  <description><![CDATA[Manamil Dev - Latest posts, tutorials and updates.]]></description>
  <language>en-us</language>
  <copyright>Copyright 2026 Manamil Dev</copyright>
  <generator>Manamil Dev RSS Generator</generator>
  <ttl>60</ttl>
  <managingEditor>muhammadmanamil@gmail.com (Manamil Dev)</managingEditor>
  <webMaster>muhammadmanamil@gmail.com (Webmaster)</webMaster>

  
  <atom:link href="https://manamil.dev/rss.xml" rel="self" type="application/rss+xml"/>

  
    
  
    <lastBuildDate>Sat, 04 Apr 2026 18:19:47 +0000</lastBuildDate>

  
      
    <item>
      <title><![CDATA[How to Use Laravel 13 AI SDK for Native AI Development | Complete Guide]]></title>
      <link>https://manamil.dev/blog/laravel/how-to-use-laravel-13-ai-sdk-for-native-ai-development-complete-guide</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/how-to-use-laravel-13-ai-sdk-for-native-ai-development-complete-guide</guid>

      
      <description><![CDATA[
        <p>Master Laravel 13&#039;s native AI SDK: build AI agents, use pgvector for semantic search, passkey auth, queue routing &amp; more. Complete guide with code examples.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/NBr8D9Fn1ZZIPjHFz7mI69sHHNKaBVjAhtTb6mVw.svg" alt="How to Use Laravel 13 AI SDK for Native AI Development Complete Guide" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <p>The Laravel ecosystem has always pushed the boundaries of what PHP developers can accomplish, but the&nbsp;<strong>Laravel 13 release <strong class="Yjhzub" data-sfc-root="c" data-sfc-cb="">March 17, 2026</strong> &nbsp;</strong>marks a genuinely transformative moment. With the introduction of the native <strong>Laravel AI SDK</strong>, the framework no longer treats artificial intelligence as an afterthought or a third-party luxury &mdash; it bakes AI capabilities directly into the core development experience. Furthermore, this release stands on the shoulders of <strong>Laravel PHP 8.3</strong>, harnessing modern language features to deliver performance, expressiveness, and reliability at every layer.</p>
<p>Understanding how to use the Laravel AI SDK effectively is not simply about learning a new package. It is about rethinking how you architect applications, how you interact with data, and how you build intelligent workflows that respond dynamically to user needs. This guide walks you through everything &mdash; from the foundational <strong>Laravel 13 features</strong> to advanced <strong>Laravel AI agent tutorial</strong> patterns &mdash; so you can confidently adopt and master this powerful toolkit.</p>
<h2>What's New in Laravel 13: A Framework Reborn</h2>
<p>Before diving into the AI SDK itself, it is essential to understand <strong>what's new in Laravel 13</strong> at a high level. The release introduces sweeping changes across routing, authentication, data handling, and developer ergonomics. Among the headline additions, <strong>Laravel passkey authentication</strong> stands out as a security-first feature that enables passwordless login using WebAuthn and FIDO2 standards. Developers can now implement biometric or hardware-key authentication with just a handful of lines &mdash; a feature that previously required complex third-party packages.</p>
<p>Equally noteworthy are the improvements to <strong>Laravel JSON API resources</strong>, which now offer richer, more expressive transformations aligned with the JSON:API specification. Additionally, <strong>Laravel queue routing</strong> receives a major upgrade, enabling developers to define intelligent routing rules that direct jobs to specific workers based on payload, priority, or even real-time system load. These foundational improvements collectively create the fertile ground on which the AI SDK flourishes.</p>
<h2>Laravel 13 vs Laravel 12: Understanding the Evolutionary Leap</h2>
<p>When comparing <strong>Laravel 13 vs Laravel 12</strong>, the differences go well beyond a version number bump. Laravel 12 delivered solid improvements in Eloquent, Blade components, and HTTP client features. However, Laravel 13 represents a paradigm shift &mdash; it is the first version to treat AI as a first-class citizen in the framework's architecture. The introduction of <strong>Laravel 13 PHP attributes</strong> further modernizes the codebase, replacing verbose configuration arrays with clean, declarative attribute syntax that feels native to <strong>Laravel PHP 8.3</strong>.</p>
<p>Moreover, <strong>Laravel 13 vs Laravel 12</strong> comparisons reveal a more opinionated approach to AI-driven development. Where Laravel 12 left AI integration entirely to community packages like Prism or OpenAI PHP, Laravel 13 provides a standardized, officially supported path. This means better documentation, tighter integration with Eloquent, first-class support in the <strong>Laravel 13 starter kit</strong>, and a long-term maintenance guarantee from the core team &mdash; a critical factor for enterprise teams evaluating production adoption.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Laravel 12</th>
<th>Laravel 13</th>
</tr>
</thead>
<tbody>
<tr>
<td>Native AI SDK</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>Passkey Auth</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>PHP 8.3 Attributes</td>
<td>Partial</td>
<td>Full</td>
</tr>
<tr>
<td>Vector Search</td>
<td>Third-party only</td>
<td>Native pgvector</td>
</tr>
<tr>
<td>JSON API Resources</td>
<td>Basic</td>
<td>Enhanced + Spec-compliant</td>
</tr>
<tr>
<td>Intelligent Queue Routing</td>
<td>Standard</td>
<td>Dynamic + Priority-based</td>
</tr>
</tbody>
</table>
<hr>
<h2>Getting Started: The Laravel 13 Starter Kit and Installation</h2>
<p>The <strong>Laravel 13 starter kit</strong> has been redesigned from the ground up to include AI-ready scaffolding out of the box. When you initialize a new project using <code>laravel new my-app --ai</code>, the installer provisions authentication, API structure, AI service bindings, and vector search configuration automatically. This dramatically reduces the time between idea and a working, intelligent prototype.</p>
<pre><code class="language-bash"># Install Laravel 13 with AI starter kit
composer create-project laravel/laravel my-ai-app
cd my-ai-app

# Install the native AI SDK
composer require laravel/ai

# Publish AI configuration and scaffolding
php artisan ai:install

# Run database migrations including vector support
php artisan migrate
</code></pre>
<p>The <strong>Laravel 13 upgrade guide</strong> for existing applications is equally well-considered. The upgrade path from Laravel 12 provides automated codemods via the <code>php artisan upgrade</code> command, which detects deprecated patterns, suggests replacements using PHP attributes, and flags areas where AI integration can enhance existing features. Consequently, teams upgrading from Laravel 12 do not face a blank-page migration; instead, they follow a structured, tool-assisted path that minimizes risk and maximizes confidence during the transition.</p>
<h2>Introducing the Laravel AI SDK: Architecture and Core Concepts</h2>
<p>The <strong>Laravel AI SDK</strong> operates through a clean, service-oriented architecture that abstracts away the differences between underlying model providers. At its core, the SDK exposes three primary interfaces: <code>AiChat</code> for conversational interactions, <code>AiCompletion</code> for single-turn text generation, and <code>AiEmbedding</code> for producing vector representations of text. Each interface binds to a configurable driver &mdash; whether that is OpenAI, Anthropic, Mistral, or a self-hosted model &mdash; making provider switching a configuration change rather than a code rewrite.</p>
<pre><code class="language-php">// config/ai.php &mdash; Configure your AI connections
return [
    'default' =&gt; env('AI_DRIVER', 'openai'),

    'connections' =&gt; [
        'openai' =&gt; [
            'driver'  =&gt; 'openai',
            'model'   =&gt; 'gpt-4o',
            'api_key' =&gt; env('OPENAI_API_KEY'),
        ],
        'anthropic' =&gt; [
            'driver'  =&gt; 'anthropic',
            'model'   =&gt; 'claude-sonnet-4-20250514',
            'api_key' =&gt; env('ANTHROPIC_API_KEY'),
        ],
    ],
];

// Using the AI facade &mdash; clean and expressive
$response = AI::chat()-&gt;send('Summarize this product description.', $text);
$embedding = AI::embedding()-&gt;embed('Search query text here');
</code></pre>
<p>Additionally, the SDK integrates tightly with Laravel's existing service container, facades, and configuration system. Developers define their AI connections in <code>config/ai.php</code>, pull them via dependency injection or the <code>AI::</code> facade, and immediately gain access to structured, chainable API calls. This architecture means that every <strong>Laravel AI agent tutorial</strong> you build naturally inherits Laravel's middleware, error handling, logging, and testing utilities &mdash; a massive productivity advantage compared to integrating standalone AI clients manually.</p>
<h2>Building Your First Laravel AI Agent: A Step-by-Step Tutorial</h2>
<p>This <strong>Laravel AI agent tutorial</strong> begins with defining an agent that can answer customer support queries. First, create an agent class using the new <code>#[AiAgent]</code> PHP attribute &mdash; a core part of <strong>Laravel 13 PHP attributes</strong> &mdash; and decorate methods with tool definitions the model can invoke during reasoning:</p>
<pre><code class="language-php">use Laravel\Ai\Attributes\AiAgent;
use Laravel\Ai\Attributes\SystemPrompt;
use Laravel\Ai\Attributes\Tool;
use Laravel\Ai\BaseAgent;

#[AiAgent(model: 'gpt-4o', temperature: 0.3)]
class SupportAgent extends BaseAgent
{
    #[SystemPrompt]
    public string $systemPrompt = 'You are a helpful support agent for Acme Corp.
        Always look up orders before responding to billing questions.';

    #[Tool(description: 'Look up an order by its ID')]
    public function lookupOrder(string $orderId): array
    {
        return Order::findOrFail($orderId)-&gt;toArray();
    }

    #[Tool(description: 'Issue a refund for a given order')]
    public function issueRefund(string $orderId, float $amount): string
    {
        RefundJob::dispatch($orderId, $amount);
        return "Refund of \${$amount} queued for order #{$orderId}.";
    }
}
</code></pre>
<p>Beyond the basic agent, you can equip it with a <code>KnowledgeBaseTool</code> that performs semantic retrieval using <strong>Laravel vector search</strong>, enabling the agent to cite real documentation in its answers. The SDK automatically serializes these tools into the model's function-calling schema, handles invocation callbacks, and manages multi-step reasoning loops &mdash; transforming a simple class definition into a fully autonomous support agent that can look up orders, issue refunds, and answer questions from your knowledge base without any additional orchestration code.</p>
<h2>Laravel Vector Search and pgvector: Powering Semantic Intelligence</h2>
<p>One of the most exciting <strong>Laravel 13 features</strong> is its native support for <strong>Laravel vector search</strong>, built on top of <strong>Laravel pgvector</strong> &mdash; the PostgreSQL extension for high-dimensional vector operations. Developers can now store, index, and query embedding vectors directly within Eloquent models using the <code>HasVectorSearch</code> trait and the <code>vector</code> column type in migrations:</p>
<pre><code class="language-php">// Migration &mdash; add vector column
Schema::create('documents', function (Blueprint $table) {
    $table-&gt;id();
    $table-&gt;string('title');
    $table-&gt;longText('content');
    $table-&gt;vector('embedding', 1536); // Dimension for text-embedding-3-small
    $table-&gt;timestamps();
});

// Model &mdash; attach vector search behavior
class Document extends Model
{
    use HasVectorSearch;
}

// Store a document with its embedding
$embedding = AI::embedding()-&gt;embed($content);
Document::create(['title' =&gt; $title, 'content' =&gt; $content, 'embedding' =&gt; $embedding]);

// Semantic search with Laravel pgvector &mdash; cosine distance
$queryEmbedding = AI::embedding()-&gt;embed($userQuery);
$results = Document::nearestNeighbors('embedding', $queryEmbedding, 'cosine')
    -&gt;where('published', true)
    -&gt;limit(5)
    -&gt;get();
</code></pre>
<p><strong>Laravel pgvector</strong> enables semantic similarity searches that go far beyond keyword matching. When a user asks a natural-language question, the application generates an embedding for that query and retrieves the most semantically similar documents using cosine distance. This capability forms the backbone of Retrieval-Augmented Generation (RAG) systems, allowing your AI agents to ground their responses in real, domain-specific knowledge. Because <strong>Laravel pgvector</strong> integrates with Eloquent's query builder, developers can combine vector similarity scores with traditional SQL filters, pagination, and eager loading &mdash; all within familiar Laravel idioms.</p>
<h2>Laravel Queue Routing for AI Workloads: Scaling Intelligently</h2>
<p>AI workloads are inherently asynchronous and resource-intensive, which is precisely why the improvements to <strong>Laravel queue routing</strong> in version 13 are so consequential. The new <code>QueueRouter</code> class allows developers to define routing rules as expressive closures or PHP attribute-decorated methods that inspect job payloads and dispatch them to optimally configured workers. For example, embedding generation jobs can route to GPU-optimized workers, while lightweight classification jobs route to standard CPU workers.</p>
<pre><code class="language-php">use Laravel\Queue\Attributes\QueueRoute;

#[QueueRoute(
    queue: fn(GenerateEmbeddingJob $job) =&gt;
        $job-&gt;document-&gt;word_count &gt; 10000 ? 'gpu-workers' : 'standard-workers',
    priority: fn(GenerateEmbeddingJob $job) =&gt;
        $job-&gt;document-&gt;is_urgent ? 'critical' : 'normal',
    retryUntil: now()-&gt;addHours(2)
)]
class GenerateEmbeddingJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue;

    public function handle(AI $ai): void
    {
        $this-&gt;document-&gt;update([
            'embedding' =&gt; $ai-&gt;embedding()-&gt;embed($this-&gt;document-&gt;content),
        ]);
    }
}
</code></pre>
<p>Moreover, <strong>Laravel queue routing</strong> now supports priority-based rerouting at runtime. If an AI job exceeds a configurable processing threshold, the system can automatically re-queue it on a higher-capacity worker pool, notifying administrators through Laravel's event system. This elastic behavior ensures that your intelligent features remain responsive even during traffic spikes, without requiring manual infrastructure intervention. Combined with Laravel Horizon's real-time monitoring dashboard, you gain complete visibility into how your AI workloads flow through the system.</p>
<h2>Laravel Passkey Authentication: Securing Your AI-Powered Applications</h2>
<p>Security deserves equal attention alongside capability, and <strong>Laravel passkey authentication</strong> delivers a modern, phishing-resistant authentication layer ideally suited to AI-powered applications. Since AI features often handle sensitive user data &mdash; personal queries, financial analysis, health information &mdash; the framework's passkey support ensures that access control meets the same standard of excellence as the features it protects.</p>
<pre><code class="language-php">// 1. Add the HasPasskeys trait to your User model
use Laravel\Passkeys\HasPasskeys;

class User extends Authenticatable
{
    use HasPasskeys;
}

// 2. Register all WebAuthn routes in one line
Route::passkeys();

// 3. Protect your AI endpoints behind passkey-verified middleware
Route::middleware(['auth:passkey'])-&gt;group(function () {
    Route::post('/ai/chat', [AiChatController::class, 'send']);
    Route::get('/ai/history', [AiChatController::class, 'history']);
});
</code></pre>
<p>Implementing <strong>Laravel passkey authentication</strong> requires minimal ceremony. The <code>HasPasskeys</code> trait, combined with the new <code>PasskeyController</code> scaffold in the <strong>Laravel 13 starter kit</strong>, handles the complete WebAuthn registration and assertion flow. Laravel manages the cryptographic challenge-response cycle, user verification storage, and session binding automatically. As a result, you can deliver enterprise-grade, passwordless security to your users without building cryptographic infrastructure from scratch &mdash; a major win for any team shipping AI features to production.</p>
<h2>Laravel JSON API Resources: Structuring AI Responses for the Modern Web</h2>
<p>When AI agents produce responses, presenting that output cleanly to frontend clients is just as important as generating it correctly. <strong>Laravel JSON API resources</strong> in version 13 provide a fluent, specification-compliant way to serialize AI responses, agent states, and vector search results into structured API payloads. The enhanced <code>JsonApiResource</code> class supports relationship inclusion, sparse fieldsets, and metadata blocks aligned with the JSON:API specification &mdash; making your AI-powered API consumable by any standards-compliant client.</p>
<pre><code class="language-php">class ConversationResource extends JsonApiResource
{
    public function toArray(Request $request): array
    {
        return [
            'type'          =&gt; 'conversation',
            'id'            =&gt; (string) $this-&gt;id,
            'attributes'    =&gt; [
                'messages'      =&gt; MessageResource::collection($this-&gt;messages),
                'citations'     =&gt; CitationResource::collection($this-&gt;citations),
                'confidence'    =&gt; $this-&gt;agent_confidence_score,
                'model_used'    =&gt; $this-&gt;model_used,
            ],
            'relationships' =&gt; [
                'user' =&gt; UserResource::make($this-&gt;user),
            ],
            'meta' =&gt; [
                'tokens_used'       =&gt; $this-&gt;total_tokens,
                'tools_invoked'     =&gt; $this-&gt;tools_invoked_count,
                'response_time_ms'  =&gt; $this-&gt;response_time_ms,
                'vector_results'    =&gt; $this-&gt;citations-&gt;count(),
            ],
        ];
    }
}
</code></pre>
<p>Developers building <strong>Laravel AI agent tutorial</strong> workflows can wrap agent responses in a <code>ConversationResource</code> that serializes the message history, tool invocations, vector search citations, and confidence scores into a single, well-structured JSON document. This structured output makes it trivial to build rich frontend experiences &mdash; streaming chat interfaces, citation cards, confidence indicators &mdash; because the data contract is consistent, predictable, and self-documenting. Consequently, the combination of the AI SDK and enhanced <strong>Laravel JSON API resources</strong> eliminates the messy, ad-hoc response shaping that typically plagues AI integration projects.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/NBr8D9Fn1ZZIPjHFz7mI69sHHNKaBVjAhtTb6mVw.svg" type="image/svg+xml" length="22751" />
        <media:content url="https://manamil.dev/storage/uploads/posts/NBr8D9Fn1ZZIPjHFz7mI69sHHNKaBVjAhtTb6mVw.svg" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Sat, 04 Apr 2026 17:45:52 +0000</pubDate>

      
                        <category><![CDATA[Laravel 13 AI SDK]]></category>
                  <category><![CDATA[Laravel 13 features]]></category>
                  <category><![CDATA[what&#039;s new Laravel 13]]></category>
                  <category><![CDATA[Laravel AI SDK]]></category>
                  <category><![CDATA[Laravel 13 release date]]></category>
                  <category><![CDATA[Laravel 13 upgrade guide]]></category>
                  <category><![CDATA[Laravel PHP 8.3]]></category>
                  <category><![CDATA[Laravel vector search]]></category>
                  <category><![CDATA[Laravel pgvector]]></category>
                  <category><![CDATA[Laravel JSON API resources]]></category>
                  <category><![CDATA[Laravel 13 vs Laravel 12]]></category>
                  <category><![CDATA[Laravel queue routing]]></category>
                  <category><![CDATA[Laravel passkey authentication]]></category>
                  <category><![CDATA[Laravel 13 PHP attributes]]></category>
                  <category><![CDATA[Laravel 13 starter kit]]></category>
                  <category><![CDATA[Laravel AI agent tutorial]]></category>
                  <category><![CDATA[native AI SDK Laravel]]></category>
                  <category><![CDATA[Laravel AI integration]]></category>
                  <category><![CDATA[PHP AI development]]></category>
                  <category><![CDATA[Laravel machine learning]]></category>
                  </item>
      
    <item>
      <title><![CDATA[AI &amp; Zero-Click Search Optimization Guide 2026: Rank in AI Overviews]]></title>
      <link>https://manamil.dev/blog/website-management/ai-zero-click-search-optimization-guide-2026-rank-in-ai-overviews</link>
      <guid isPermaLink="true">https://manamil.dev/blog/website-management/ai-zero-click-search-optimization-guide-2026-rank-in-ai-overviews</guid>

      
      <description><![CDATA[
        <p>Master Zero-Click SEO and AI Overview optimization. Learn how to get cited by Gemini and ChatGPT while maintaining topical authority in 2026.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/VOiek6WeAsDhEdpKcE14M6b00h8QMPREAwll7Ne9.png" alt="AI &amp; Zero-Click Search Optimization Guide 2026: Rank in AI Overviews" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 data-path-to-node="6">The 2026 Guide to AI &amp; Zero-Click Search Optimization</h2>
<h3 data-path-to-node="7">1. The "Answer-First" Content Framework</h3>
<p data-path-to-node="8">AI engines are designed to find and synthesize information quickly. To be the source they choose, you must structure your content for <strong data-path-to-node="8" data-index-in-node="134">Machine Parsability</strong>.</p>
<ul data-path-to-node="9">
<li>
<p data-path-to-node="9,0,0"><strong data-path-to-node="9,0,0" data-index-in-node="0">The Citation Block:</strong> Start every major section with a 40&ndash;60 word "direct answer." This is a concise, factual summary that an AI can lift and cite verbatim.</p>
</li>
<li>
<p data-path-to-node="9,1,0"><strong data-path-to-node="9,1,0" data-index-in-node="0">Question-Based H2s:</strong> Use exact user queries as your subheadings (e.g., <em data-path-to-node="9,1,0" data-index-in-node="70">"How much does X cost in 2026?"</em>). This helps AI bots map your content to specific user intents.</p>
</li>
<li>
<p data-path-to-node="9,2,0"><strong data-path-to-node="9,2,0" data-index-in-node="0">Statistical Weight:</strong> AI models prioritize content with hard data. Instead of saying <em data-path-to-node="9,2,0" data-index-in-node="83">"Most users prefer X,"</em> say <em data-path-to-node="9,2,0" data-index-in-node="110">"67% of users in 2026 reported a preference for X."</em></p>
</li>
</ul>
<h3 data-path-to-node="10">2. Mastering E-E-A-T for AI Trust</h3>
<p data-path-to-node="11">As AI-generated "spam" content increases, search engines use <strong data-path-to-node="11" data-index-in-node="61">E-E-A-T</strong> (Experience, Expertise, Authoritativeness, Trust) as a filter.</p>
<ul data-path-to-node="12">
<li>
<p data-path-to-node="12,0,0"><strong data-path-to-node="12,0,0" data-index-in-node="0">Verified Author Entities:</strong> Every post must be linked to a real human expert with a verified Knowledge Graph presence.</p>
</li>
<li>
<p data-path-to-node="12,1,0"><strong data-path-to-node="12,1,0" data-index-in-node="0">First-Person Proof:</strong> Include "Experience" signals that AI cannot fake: original photos, specific case study results, and unique personal insights.</p>
</li>
<li>
<p data-path-to-node="12,2,0"><strong data-path-to-node="12,2,0" data-index-in-node="0">Trust &amp; Security:</strong> A secure site is a non-negotiable trust signal. Before optimizing your content, ensure your technical foundation is solid by using high-quality <strong data-path-to-node="12,2,0" data-index-in-node="162"><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><a class="ng-star-inserted" href="https://manamil.dev/../../../../tools/ssl-server-test" target="_blank" rel="noopener" data-hveid="0" data-ved="0CAAQ_4QMahcKEwjGgOnRp5iSAxUAAAAAHQAAAAAQbg">SSL check tools</a><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----></strong> to verify your site&rsquo;s encryption and security status.</p>
</li>
</ul>
<h3 data-path-to-node="13">3. Strategic Schema Markup (The AI's Navigation)</h3>
<p data-path-to-node="14">Schema markup is the "Nutrition Label" for your website. In 2026, these three are essential for Zero-Click results:</p>
<ul data-path-to-node="15">
<li>
<p data-path-to-node="15,0,0"><strong data-path-to-node="15,0,0" data-index-in-node="0">FAQ Schema:</strong> Directly feeds the "People Also Ask" boxes and AI Q&amp;A modules.</p>
</li>
<li>
<p data-path-to-node="15,1,0"><strong data-path-to-node="15,1,0" data-index-in-node="0">Organization Schema:</strong> Helps AI engines identify your brand as an authority in its niche.</p>
</li>
<li>
<p data-path-to-node="15,2,0"><strong data-path-to-node="15,2,0" data-index-in-node="0">HowTo Schema:</strong> Perfect for capturing step-by-step "Zero-Click" snippets for tutorial searches.</p>
</li>
</ul>
<h3 data-path-to-node="16">4. Moving Beyond Clicks: New KPIs</h3>
<p data-path-to-node="17">Traditional "Traffic" is becoming a secondary metric. In a zero-click world, you must track:</p>
<ol start="1" data-path-to-node="18">
<li>
<p data-path-to-node="18,0,0"><strong data-path-to-node="18,0,0" data-index-in-node="0">Inclusion Rate:</strong> How often your brand is cited in AI Overviews.</p>
</li>
<li>
<p data-path-to-node="18,1,0"><strong data-path-to-node="18,1,0" data-index-in-node="0">Brand Visibility:</strong> Impressions in the "Knowledge Panel" or "Local Pack."</p>
</li>
<li>
<p data-path-to-node="18,2,0"><strong data-path-to-node="18,2,0" data-index-in-node="0">Share of Voice:</strong> What percentage of an AI's summary is based on your data?</p>
</li>
</ol>
<h2 data-path-to-node="20">KPI Comparison Table: 2020 vs. 2026</h2>
<table data-path-to-node="21">
<thead>
<tr>
<td><strong>Metric</strong></td>
<td><strong>Old Way (2020)</strong></td>
<td><strong>New Way (2026)</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td><span data-path-to-node="21,1,0,0"><strong data-path-to-node="21,1,0,0" data-index-in-node="0">Success</strong></span></td>
<td><span data-path-to-node="21,1,1,0">Keyword Rankings (#1-10)</span></td>
<td><span data-path-to-node="21,1,2,0"><strong data-path-to-node="21,1,2,0" data-index-in-node="0">AI Citation Frequency</strong> (%)</span></td>
</tr>
<tr>
<td><span data-path-to-node="21,2,0,0"><strong data-path-to-node="21,2,0,0" data-index-in-node="0">Traffic</strong></span></td>
<td><span data-path-to-node="21,2,1,0">Total Organic Clicks</span></td>
<td><span data-path-to-node="21,2,2,0"><strong data-path-to-node="21,2,2,0" data-index-in-node="0">Assisted Conversions</strong> (via AI)</span></td>
</tr>
<tr>
<td><span data-path-to-node="21,3,0,0"><strong data-path-to-node="21,3,0,0" data-index-in-node="0">Authority</strong></span></td>
<td><span data-path-to-node="21,3,1,0">Backlink Count (DR/DA)</span></td>
<td><span data-path-to-node="21,3,2,0"><strong data-path-to-node="21,3,2,0" data-index-in-node="0">Entity Relationship Strength</strong></span></td>
</tr>
<tr>
<td><span data-path-to-node="21,4,0,0"><strong data-path-to-node="21,4,0,0" data-index-in-node="0">Engagement</strong></span></td>
<td><span data-path-to-node="21,4,1,0">Bounce Rate</span></td>
<td><span data-path-to-node="21,4,2,0"><strong data-path-to-node="21,4,2,0" data-index-in-node="0">Interaction to Next Paint (INP)</strong></span></td>
</tr>
<tr>
<td><span data-path-to-node="21,5,0,0"><strong data-path-to-node="21,5,0,0" data-index-in-node="0">Security</strong></span></td>
<td><span data-path-to-node="21,5,1,0">"Has SSL?" (Yes/No)</span></td>
<td><span data-path-to-node="21,5,2,0"><strong data-path-to-node="21,5,2,0" data-index-in-node="0">Trust Score</strong> (Continuous Auditing)</span></td>
</tr>
</tbody>
</table>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/VOiek6WeAsDhEdpKcE14M6b00h8QMPREAwll7Ne9.png" type="image/png" length="1638047" />
        <media:content url="https://manamil.dev/storage/uploads/posts/VOiek6WeAsDhEdpKcE14M6b00h8QMPREAwll7Ne9.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 19 Jan 2026 19:16:38 +0000</pubDate>

      
                        <category><![CDATA[Zero-click search optimization]]></category>
                  <category><![CDATA[AI Overview SEO]]></category>
                  <category><![CDATA[Generative Engine Optimization (GEO)]]></category>
                  <category><![CDATA[Featured Snippets 2026]]></category>
                  <category><![CDATA[Topical Authority.]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Unmasking the N+1 Query Problem in Laravel: Your Guide to Faster Apps]]></title>
      <link>https://manamil.dev/blog/laravel/how-do-you-handle-the-n1-query-problem-and-why-is-it-critical-for-performance</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/how-do-you-handle-the-n1-query-problem-and-why-is-it-critical-for-performance</guid>

      
      <description><![CDATA[
        <p>Learn what the N+1 query problem is in Laravel, why it slows down your application, and how to fix it with eager loading. Essential performance tips for beginners.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/UcErSgl4n0HCcxG7JBAwuGMTmGEfl9P00JNCHxMr.png" alt="Unmasking the N+1 Query Problem in Laravel: Your Guide to Faster Apps" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 data-path-to-node="5">The Hidden Performance Killer</h2>
<p data-path-to-node="6">Have you ever built a Laravel application and noticed it felt a bit sluggish, especially when loading pages with lots of related information? You're not alone. Many developers, particularly beginners, unknowingly fall victim to a common pitfall called the "N+1 Query Problem."</p>
<p data-path-to-node="7">But don't worry! In this post, we're going to demystify what the N+1 problem is, show you why it's a performance killer, and give you the simple, yet powerful, solution that will make your Laravel apps feel lightning fast.</p>
<h2 data-path-to-node="8">What Exactly is the "N+1 Query Problem"?</h2>
<p data-path-to-node="9">Imagine you have a blog. Each <code data-path-to-node="9" data-index-in-node="30">Post</code> has an <code data-path-to-node="9" data-index-in-node="42">Author</code>. Now, let's say you want to display a list of all your blog posts and, next to each post title, show the name of its author.</p>
<p data-path-to-node="10">Here's how you might <em data-path-to-node="10" data-index-in-node="21">think</em> to do it:</p>
<ol start="1" data-path-to-node="11">
<li>
<p data-path-to-node="11,0,0"><strong data-path-to-node="11,0,0" data-index-in-node="0">First Query:</strong> Get all the posts: <code data-path-to-node="11,0,0" data-index-in-node="32">SELECT * FROM posts;</code> (This is 1 query).</p>
</li>
<li>
<p data-path-to-node="11,1,0"><strong data-path-to-node="11,1,0" data-index-in-node="0">Subsequent Queries:</strong> For <em data-path-to-node="11,1,0" data-index-in-node="24">each</em> post you retrieved, you then fetch its author: <code data-path-to-node="11,1,0" data-index-in-node="76">SELECT * FROM authors WHERE id = [post_author_id];</code></p>
</li>
</ol>
<p data-path-to-node="12">If you have 10 posts, this means: 1 (query for all posts) + 10 (queries for each author) = <strong data-path-to-node="12" data-index-in-node="91">11 database queries!</strong></p>
<p data-path-to-node="13">This is your "N+1" problem in action:</p>
<ul data-path-to-node="14">
<li>
<p data-path-to-node="14,0,0"><strong data-path-to-node="14,0,0" data-index-in-node="0">1</strong> is the initial query to get the main data (all posts).</p>
</li>
<li>
<p data-path-to-node="14,1,0"><strong data-path-to-node="14,1,0" data-index-in-node="0">N</strong> is the number of additional queries fired for each related piece of data (each author).</p>
</li>
</ul>
<p data-path-to-node="15">As your <code data-path-to-node="15" data-index-in-node="8">N</code> (number of posts) grows, so does the number of database queries, grinding your application to a halt. This is particularly bad in web applications where every millisecond counts for user experience.</p>
<h2 data-path-to-node="16">Why is This a Problem? (Beyond Just Math)</h2>
<p data-path-to-node="17">"So what if it's 11 queries instead of 2?" you might ask. Here's why it matters:</p>
<ul data-path-to-node="18">
<li>
<p data-path-to-node="18,0,0"><strong data-path-to-node="18,0,0" data-index-in-node="0">Database is Slow:</strong> Database operations are one of the slowest parts of any web application. Every time your application talks to the database, there's network overhead, processing time, and resource consumption. More queries mean more waiting.</p>
</li>
<li>
<p data-path-to-node="18,1,0"><strong data-path-to-node="18,1,0" data-index-in-node="0">Server Resources:</strong> Your server has to work harder to make all those individual database connections and process the results.</p>
</li>
<li>
<p data-path-to-node="18,2,0"><strong data-path-to-node="18,2,0" data-index-in-node="0">User Experience (UX):</strong> A slow website is a frustrating website. Users expect pages to load instantly. The N+1 problem directly impacts how quickly your pages render.</p>
</li>
<li>
<p data-path-to-node="18,3,0"><strong data-path-to-node="18,3,0" data-index-in-node="0">Scalability:</strong> As your application grows and more users access it, the N+1 problem becomes a catastrophic bottleneck.</p>
</li>
</ul>
<h2 data-path-to-node="19">The Solution: Eager Loading with <code data-path-to-node="19" data-index-in-node="33">with()</code></h2>
<p data-path-to-node="20">Laravel, being the awesome framework it is, provides a super elegant solution for the N+1 problem: <strong data-path-to-node="20" data-index-in-node="99">Eager Loading</strong>.</p>
<p data-path-to-node="21">Instead of fetching related data one by one, eager loading tells Laravel to fetch all the related data in <strong data-path-to-node="21" data-index-in-node="106">just one extra query</strong> when the initial query is made.</p>
<p data-path-to-node="22">Let's revisit our blog post example:</p>
<p data-path-to-node="23"><strong data-path-to-node="23" data-index-in-node="0">Before (N+1 Problem):</strong></p>
<p><!----><!----><!----><!----><!----><!----><!----></p>
<div class="code-block ng-tns-c566977354-41 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwjj8qqeoZiSAxUAAAAAHQAAAAAQZg">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c566977354-41 ng-star-inserted"><span class="ng-tns-c566977354-41">PHP</span>
<div class="buttons ng-tns-c566977354-41 ng-star-inserted"><!----><!----></div>
<!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c566977354-41">
<div class="animated-opacity ng-tns-c566977354-41">
<pre class="ng-tns-c566977354-41"><code class="code-container formatted ng-tns-c566977354-41" role="text" data-test-id="code-content"><span class="hljs-comment">// In your controller or route</span>
<span class="hljs-variable">$posts</span> = App\Models\Post::all();

<span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$posts</span> <span class="hljs-keyword">as</span> <span class="hljs-variable">$post</span>) {
    <span class="hljs-keyword">echo</span> <span class="hljs-variable">$post</span>-&gt;title . <span class="hljs-string">' by '</span> . <span class="hljs-variable">$post</span>-&gt;author-&gt;name; <span class="hljs-comment">// Each time author is accessed, a new query fires</span>
}
</code></pre>
<!----></div>
</div>
</div>
<p><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----></p>
<p data-path-to-node="25">This code results in 1 + N queries.</p>
<p data-path-to-node="26"><strong data-path-to-node="26" data-index-in-node="0">After (Eager Loaded Solution):</strong></p>
<p><!----><!----><!----><!----><!----><!----><!----></p>
<div class="code-block ng-tns-c566977354-42 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwjj8qqeoZiSAxUAAAAAHQAAAAAQZw">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c566977354-42 ng-star-inserted"><span class="ng-tns-c566977354-42">PHP</span>
<div class="buttons ng-tns-c566977354-42 ng-star-inserted"><!----><!----></div>
<!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c566977354-42">
<div class="animated-opacity ng-tns-c566977354-42">
<pre class="ng-tns-c566977354-42"><code class="code-container formatted ng-tns-c566977354-42" role="text" data-test-id="code-content"><span class="hljs-comment">// In your controller or route</span>
<span class="hljs-variable">$posts</span> = App\Models\Post::with(<span class="hljs-string">'author'</span>)-&gt;get();

<span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$posts</span> <span class="hljs-keyword">as</span> <span class="hljs-variable">$post</span>) {
    <span class="hljs-keyword">echo</span> <span class="hljs-variable">$post</span>-&gt;title . <span class="hljs-string">' by '</span> . <span class="hljs-variable">$post</span>-&gt;author-&gt;name; <span class="hljs-comment">// Author data is already loaded!</span>
}
</code></pre>
<!----></div>
</div>
</div>
<p><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----></p>
<p data-path-to-node="28">The magic is in <code data-path-to-node="28" data-index-in-node="16">-&gt;with('author')</code>. What happens now is:</p>
<ol start="1" data-path-to-node="29">
<li>
<p data-path-to-node="29,0,0"><strong data-path-to-node="29,0,0" data-index-in-node="0">First Query:</strong> <code data-path-to-node="29,0,0" data-index-in-node="13">SELECT * FROM posts;</code> (Still 1 query).</p>
</li>
<li>
<p data-path-to-node="29,1,0"><strong data-path-to-node="29,1,0" data-index-in-node="0">Second Query:</strong> <code data-path-to-node="29,1,0" data-index-in-node="14">SELECT * FROM authors WHERE id IN (1, 2, 3, ...);</code> (A <em data-path-to-node="29,1,0" data-index-in-node="67">single</em> query to get <em data-path-to-node="29,1,0" data-index-in-node="87">all</em> authors whose IDs were found in the posts).</p>
</li>
</ol>
<p data-path-to-node="30">Now, if you have 10 posts, you're only making <strong data-path-to-node="30" data-index-in-node="46">2 database queries</strong> instead of 11! Imagine the difference with hundreds or thousands of posts.</p>
<h2 data-path-to-node="31">How to Implement Eager Loading (Step-by-Step for Beginners)</h2>
<ol start="1" data-path-to-node="32">
<li>
<p data-path-to-node="32,0,0"><strong data-path-to-node="32,0,0" data-index-in-node="0">Define Relationships:</strong> Ensure you have defined the relationships in your Eloquent models. For our example, in <code data-path-to-node="32,0,0" data-index-in-node="109">App\Models\Post.php</code>:</p>
<!----><!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c566977354-43 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwjj8qqeoZiSAxUAAAAAHQAAAAAQaA">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c566977354-43 ng-star-inserted"><span class="ng-tns-c566977354-43">PHP</span><!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c566977354-43">
<div class="animated-opacity ng-tns-c566977354-43">
<pre class="ng-tns-c566977354-43"><code class="code-container formatted ng-tns-c566977354-43" role="text" data-test-id="code-content"><span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Factories</span>\<span class="hljs-title">HasFactory</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">HasFactory</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">author</span>()
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;belongsTo(Author::class);
    }
}
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<p data-path-to-node="32,0,2">And in <code data-path-to-node="32,0,2" data-index-in-node="7">App\Models\Author.php</code>:</p>
<!----><!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c566977354-44 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwjj8qqeoZiSAxUAAAAAHQAAAAAQaQ">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c566977354-44 ng-star-inserted"><span class="ng-tns-c566977354-44">PHP</span><!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c566977354-44">
<div class="animated-opacity ng-tns-c566977354-44">
<pre class="ng-tns-c566977354-44"><code class="code-container formatted ng-tns-c566977354-44" role="text" data-test-id="code-content"><span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Factories</span>\<span class="hljs-title">HasFactory</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Author</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">HasFactory</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">posts</span>()
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;hasMany(Post::class);
    }
}
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----></li>
<li>
<p data-path-to-node="32,1,0"><strong data-path-to-node="32,1,0" data-index-in-node="0">Use <code data-path-to-node="32,1,0" data-index-in-node="4">with()</code> in your Query:</strong> Wherever you fetch your <code data-path-to-node="32,1,0" data-index-in-node="50">Post</code> data, add <code data-path-to-node="32,1,0" data-index-in-node="65">-&gt;with('author')</code>:</p>
<!----><!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c566977354-45 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwjj8qqeoZiSAxUAAAAAHQAAAAAQag">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c566977354-45 ng-star-inserted"><span class="ng-tns-c566977354-45">PHP</span><!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c566977354-45">
<div class="animated-opacity ng-tns-c566977354-45">
<pre class="ng-tns-c566977354-45"><code class="code-container formatted ng-tns-c566977354-45" role="text" data-test-id="code-content"><span class="hljs-variable">$posts</span> = App\Models\Post::with(<span class="hljs-string">'author'</span>)-&gt;get();
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<p data-path-to-node="32,1,2">You can eager load multiple relationships too: <code data-path-to-node="32,1,2" data-index-in-node="47">-&gt;with(['author', 'comments', 'tags'])-&gt;get()</code>.</p>
</li>
</ol>
<h2 data-path-to-node="33">Advanced Tip: Monitoring for N+1 Problems</h2>
<p data-path-to-node="34">For truly robust applications, don't just guess! Laravel offers excellent tools to help you identify N+1 problems:</p>
<ul data-path-to-node="35">
<li>
<p data-path-to-node="35,0,0"><strong data-path-to-node="35,0,0" data-index-in-node="0">Laravel Debugbar:</strong> A fantastic package that overlays debug information on your pages, including all executed database queries. It will visually highlight N+1 issues.</p>
</li>
<li>
<p data-path-to-node="35,1,0"><strong data-path-to-node="35,1,0" data-index-in-node="0">Laravel Telescope:</strong> A more comprehensive debugging assistant that provides insights into your application's requests, exceptions, mail, notifications, and, crucially, database queries, making N+1 detection very easy.</p>
</li>
</ul>
<h2 data-path-to-node="36">Build Faster, Smarter Laravel Apps</h2>
<p data-path-to-node="37">The N+1 Query Problem is a fundamental concept in optimizing Laravel application performance. By understanding how it works and consistently applying eager loading with <code data-path-to-node="37" data-index-in-node="169">-&gt;with()</code>, you can dramatically reduce database queries, speed up your applications, and provide a much better experience for your users.</p>
<p data-path-to-node="38">Start using <code data-path-to-node="38" data-index-in-node="12">with()</code> today, and watch your Laravel apps fly!</p>
<h2 data-path-to-node="3">Frequently Asked Questions (FAQ)</h2>
<h3 data-path-to-node="4">1. How can I tell if my Laravel app has an N+1 problem?</h3>
<p data-path-to-node="5">The easiest way is to use a tool like <strong data-path-to-node="5" data-index-in-node="38">Laravel Debugbar</strong>. <span class="citation-3 citation-end-3">When you load a page, the "Queries" tab will show you a list of all database calls.<sup class="superscript" data-turn-source-index="1"><!----></sup></span> If you see the same query repeating multiple times with only a different ID (e.g., <code data-path-to-node="5" data-index-in-node="223">SELECT * FROM authors WHERE id = 1</code>, then <code data-path-to-node="5" data-index-in-node="264">id = 2</code>, etc.), you have an N+1 problem.<!----></p>
<h3 data-path-to-node="6">2. Can I eager load nested relationships (e.g., Post -&gt; Author -&gt; Profile)?</h3>
<p data-path-to-node="7">Yes! Laravel makes this easy using <strong data-path-to-node="7" data-index-in-node="35">Dot Notation</strong>. If you want to load the author and the author's profile in one go, you can write:</p>
<p data-path-to-node="8"><code data-path-to-node="8" data-index-in-node="0">$posts = Post::with('author.profile')-&gt;get();</code></p>
<p data-path-to-node="9">This will fetch all three levels of data with minimal queries.</p>
<h3 data-path-to-node="10">3. Is Eager Loading always better than Lazy Loading?</h3>
<p data-path-to-node="11">Almost always, yes. However, if you are only displaying one single record (like a single Post profile page), the difference is negligible. Eager Loading shines when you are looping through <strong data-path-to-node="11" data-index-in-node="189">collections</strong> (lists) of data.</p>
<h3 data-path-to-node="12">4. What is the difference between <code data-path-to-node="12" data-index-in-node="34">with()</code> and <code data-path-to-node="12" data-index-in-node="45">load()</code>?</h3>
<ul data-path-to-node="13">
<li>
<p data-path-to-node="13,0,0"><strong data-path-to-node="13,0,0" data-index-in-node="0"><code data-path-to-node="13,0,0" data-index-in-node="0"><span class="citation-2">with()</span></code></strong><span class="citation-2"> is for </span><strong data-path-to-node="13,0,0" data-index-in-node="14"><span class="citation-2">Eager Loading</span></strong><span class="citation-2">: You use it </span><em data-path-to-node="13,0,0" data-index-in-node="40"><span class="citation-2">before</span></em><span class="citation-2"> the query is executed (e.g., </span><code data-path-to-node="13,0,0" data-index-in-node="76"><span class="citation-2">Post::with('author')-&gt;get()</span></code><span class="citation-2 citation-end-2">).<sup class="superscript" data-turn-source-index="2"><!----></sup></span><!----></p>
<!----><!----><!----><!----><!----><!----><!----><!----><!----></li>
<li>
<p data-path-to-node="13,1,0"><strong data-path-to-node="13,1,0" data-index-in-node="0"><code data-path-to-node="13,1,0" data-index-in-node="0">load()</code></strong> is for <strong data-path-to-node="13,1,0" data-index-in-node="14">Lazy Eager Loading</strong>: You use it <em data-path-to-node="13,1,0" data-index-in-node="45">after</em> you have already retrieved the models (e.g., <code data-path-to-node="13,1,0" data-index-in-node="96">$posts-&gt;load('author')</code>). This is useful if you only need the related data based on a certain condition.</p>
</li>
</ul>
<h3 data-path-to-node="14">5. Can I eager load specific columns only to save memory?</h3>
<p data-path-to-node="15">Yes! To keep your app even faster, you can specify columns like this:</p>
<p data-path-to-node="16"><code data-path-to-node="16" data-index-in-node="0">$posts = Post::with('author:id,name')-&gt;get();</code></p>
<h3 data-path-to-node="14">6. Can I eager load specific columns only to save memory?</h3>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/UcErSgl4n0HCcxG7JBAwuGMTmGEfl9P00JNCHxMr.png" type="image/png" length="1084701" />
        <media:content url="https://manamil.dev/storage/uploads/posts/UcErSgl4n0HCcxG7JBAwuGMTmGEfl9P00JNCHxMr.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 19 Jan 2026 18:51:27 +0000</pubDate>

      
                        <category><![CDATA[Laravel N+1 Query Problem]]></category>
                  <category><![CDATA[Laravel performance]]></category>
                  <category><![CDATA[Laravel eager loading]]></category>
                  <category><![CDATA[Laravel optimization]]></category>
                  <category><![CDATA[Laravel database queries]]></category>
                  <category><![CDATA[Eloquent N+1]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Soft Deletes vs Permanent Deletes in Laravel | Complete Guide with Examples]]></title>
      <link>https://manamil.dev/blog/laravel/soft-deletes-vs-permanent-deletes-in-laravel-complete-guide-with-examples</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/soft-deletes-vs-permanent-deletes-in-laravel-complete-guide-with-examples</guid>

      
      <description><![CDATA[
        <p>Learn the difference between soft deletes and permanent deletes in Laravel. Understand how to implement soft delete, restore deleted records, and manage permanent deletes with practical examples.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/okbIZu4UCw2NkZsMrYPtx9Tfe2mcaQnCP0zScs8S.png" alt="Soft Deletes vs Permanent Deletes in Laravel | Complete Guide with Examples" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <p data-start="868" data-end="1119">Laravel is a popular PHP framework that provides a clean and elegant syntax for web development. One of the most important aspects of managing database records in Laravel is <strong data-start="1042" data-end="1059">deleting data</strong>. But did you know Laravel provides two types of deletion?</p>
<ol data-start="1121" data-end="1287">
<li data-start="1121" data-end="1211">
<p data-start="1124" data-end="1211"><strong data-start="1124" data-end="1140">Soft Deletes</strong> &ndash; Temporarily delete a record without removing it from the database.</p>
</li>
<li data-start="1212" data-end="1287">
<p data-start="1215" data-end="1287"><strong data-start="1215" data-end="1236">Permanent Deletes</strong> &ndash; Permanently remove a record from the database.</p>
</li>
</ol>
<p data-start="1289" data-end="1400">Understanding the difference is crucial for data management, auditing, and recovery in real-world applications.</p>
<h2 data-start="1407" data-end="1441">Soft Deletes in Laravel</h2>
<p data-start="1443" data-end="1630">Soft deletes allow you to <strong data-start="1469" data-end="1497">mark a record as deleted</strong> without actually removing it from the database. This is useful when you want to <strong data-start="1578" data-end="1629">keep a record for recovery or auditing purposes</strong>.</p>
<h2 data-start="1632" data-end="1662">How Soft Deletes Work</h2>
<p data-start="1663" data-end="1855">When you enable soft deletes in a model, Laravel adds a <code data-start="1719" data-end="1731">deleted_at</code> timestamp column. If this column is null, the record is considered active; if it has a timestamp, it is considered deleted.</p>
<h3 data-start="1857" data-end="1873"><strong data-start="1862" data-end="1873">Example</strong></h3>
<ol data-start="1875" data-end="1958">
<li data-start="1875" data-end="1958">
<p data-start="1878" data-end="1958"><strong data-start="1878" data-end="1891">Migration</strong><br data-start="1891" data-end="1894">Add soft deletes to your table using the <code data-start="1935" data-end="1950">softDeletes()</code> method:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>use Illuminate\Database\Migrations\Migration;<br>use Illuminate\Database\Schema\Blueprint;<br>use Illuminate\Support\Facades\Schema;</p>
<p>class CreatePostsTable extends Migration<br>{<br>&nbsp; &nbsp; public function up()<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; Schema::create('posts', function (Blueprint $table) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $table-&gt;id();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $table-&gt;string('title');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $table-&gt;text('content');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $table-&gt;timestamps();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $table-&gt;softDeletes(); // Adds deleted_at column<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; public function down()<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; Schema::dropIfExists('posts');<br>&nbsp; &nbsp; }<br>}</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
</li>
<li data-start="1875" data-end="1958"><strong>Model Setup</strong><br>&lt;pre&gt;&lt;code&gt;
<p>use Illuminate\Database\Eloquent\Model;<br>use Illuminate\Database\Eloquent\SoftDeletes;</p>
<p>class Post extends Model<br>{<br>&nbsp; &nbsp; use SoftDeletes; // Enable soft deletes<br>}</p>
&lt;/code&gt;&lt;/pre&gt;</li>
<li data-start="1875" data-end="1958"><strong>Usage<br></strong>&lt;pre&gt;&lt;code&gt;
<p>// Soft delete a record<br>$post = Post::find(1);<br>$post-&gt;delete(); // Sets deleted_at timestamp</p>
<p>// Retrieve all posts including soft deleted<br>$allPosts = Post::withTrashed()-&gt;get();</p>
<p>// Retrieve only soft deleted posts<br>$deletedPosts = Post::onlyTrashed()-&gt;get();</p>
<p>// Restore soft deleted post<br>$post-&gt;restore();</p>
&lt;/code&gt;&lt;/pre&gt;</li>
</ol>
<h2>Benefits of Soft Deletes</h2>
<ul>
<li data-start="3089" data-end="3139">
<p data-start="3091" data-end="3139">Allows recovery of accidentally deleted records.</p>
</li>
<li data-start="3140" data-end="3177">
<p data-start="3142" data-end="3177">Keeps historical data for auditing.</p>
</li>
<li data-start="3178" data-end="3227">
<p data-start="3180" data-end="3227">Doesn&rsquo;t permanently lose important information.</p>
</li>
</ul>
<h2 data-start="3234" data-end="3273">Permanent Deletes in Laravel</h2>
<p data-start="3275" data-end="3435">Permanent deletes, as the name suggests, <strong data-start="3316" data-end="3345">remove records completely</strong> from the database. Once deleted, the data cannot be recovered (unless you have a backup).<br>&lt;pre&gt;&lt;code&gt;// Permanent delete a record<br>$post = Post::find(1);<br>$post-&gt;forceDelete(); // Completely removes record from DB<br>&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="3275" data-end="3435">Or, without soft deletes enabled:</p>
<p data-start="3275" data-end="3435">&lt;pre&gt;&lt;code&gt;$post = Post::find(1);<br>$post-&gt;delete(); // Deletes record permanently<br>&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="3275" data-end="3435">When to Use Permanent Deletes</h2>
<ul>
<li data-start="3731" data-end="3762">
<p data-start="3733" data-end="3762">Removing temporary test data.</p>
</li>
<li data-start="3763" data-end="3839">
<p data-start="3765" data-end="3839">Deleting records that are no longer needed for business or legal purposes.</p>
</li>
<li data-start="3840" data-end="3886">
<p data-start="3842" data-end="3886">Freeing up storage space in large databases.</p>
</li>
</ul>
<h2>Key Differences Between Soft Deletes and Permanent Deletes</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Soft Deletes</th>
<th>Permanent Deletes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data Removal</td>
<td>Marks <code>deleted_at</code> timestamp; record remains in DB</td>
<td>Completely removes record from DB</td>
</tr>
<tr>
<td>Recovery</td>
<td>Can restore deleted records</td>
<td>Cannot restore deleted records</td>
</tr>
<tr>
<td>Use Case</td>
<td>Auditing, accidental deletion recovery</td>
<td>Permanent cleanup or obsolete data removal</td>
</tr>
<tr>
<td>Querying</td>
<td>Use <code>withTrashed()</code> or <code>onlyTrashed()</code> to include soft deleted</td>
<td>Only active records exist; deleted records gone</td>
</tr>
</tbody>
</table>
<p data-start="3275" data-end="3435">Soft deletes are great for <strong data-start="3968" data-end="3991">safety and auditing</strong>, while permanent deletes are better for <strong data-start="4032" data-end="4064">cleaning up unnecessary data</strong>. Using the right deletion method helps maintain a clean, reliable database in Laravel applications.</p>
<h3 data-start="152" data-end="238">1. What is the difference between soft deletes and permanent deletes in Laravel?</h3>
<ul data-start="239" data-end="505">
<li data-start="239" data-end="378">
<p data-start="241" data-end="378"><strong data-start="241" data-end="258">Soft Deletes:</strong> Marks a record as deleted by setting a <code data-start="298" data-end="310">deleted_at</code> timestamp but keeps it in the database. You can restore it later.</p>
</li>
<li data-start="379" data-end="505">
<p data-start="381" data-end="505"><strong data-start="381" data-end="403">Permanent Deletes:</strong> Completely removes the record from the database. Recovery is not possible unless you have a backup.</p>
</li>
</ul>
<h3 data-start="507" data-end="556">2. How do I enable soft deletes in Laravel?</h3>
<ul data-start="557" data-end="700">
<li data-start="557" data-end="644">
<p data-start="559" data-end="644">Add the <code data-start="567" data-end="582">softDeletes()</code> method in your migration to create the <code data-start="622" data-end="634">deleted_at</code> column.</p>
</li>
<li data-start="645" data-end="700">
<p data-start="647" data-end="700">Use the <code data-start="655" data-end="668">SoftDeletes</code> trait in your Eloquent model.</p>
</li>
</ul>
<h3 data-start="702" data-end="751">3. How can I retrieve soft-deleted records?</h3>
<ul data-start="752" data-end="895">
<li data-start="752" data-end="828">
<p data-start="754" data-end="828">Use <code data-start="758" data-end="773">withTrashed()</code> to retrieve all records including soft-deleted ones.</p>
</li>
<li data-start="829" data-end="895">
<p data-start="831" data-end="895">Use <code data-start="835" data-end="850">onlyTrashed()</code> to retrieve <strong data-start="863" data-end="871">only</strong> soft-deleted records.</p>
</li>
</ul>
<h3 data-start="897" data-end="946">4. How can I restore a soft-deleted record?</h3>
<p>&lt;pre&gt;&lt;code&gt;$post = Post::withTrashed()-&gt;find(1);<br>$post-&gt;restore();<br>&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="1015" data-end="1055">5. When should I use soft deletes?</h3>
<ul data-start="1056" data-end="1202">
<li data-start="1056" data-end="1092">
<p data-start="1058" data-end="1092">To prevent accidental data loss.</p>
</li>
<li data-start="1093" data-end="1141">
<p data-start="1095" data-end="1141">To maintain historical records for auditing.</p>
</li>
<li data-start="1142" data-end="1202">
<p data-start="1144" data-end="1202">When you may need to recover deleted data in the future.</p>
</li>
</ul>
<h3 data-start="1204" data-end="1250">6. How do I permanently delete a record?</h3>
<ul data-start="1251" data-end="1283">
<li data-start="1251" data-end="1283">
<p data-start="1253" data-end="1283">If soft deletes are enabled:<br>&lt;pre&gt;&lt;code&gt;$post-&gt;forceDelete(); // permanently deletes the record<br>&lt;/code&gt;&lt;/pre&gt;</p>
</li>
<li data-start="1251" data-end="1283">If soft deletes are not enabled:<br>&lt;pre&gt;&lt;code&gt;$post-&gt;delete(); // permanently deletes the record<br>&lt;/code&gt;&lt;/pre&gt;</li>
</ul>
<h3 data-start="1451" data-end="1496">7. When should I use permanent deletes?</h3>
<ul data-start="1497" data-end="1660">
<li data-start="1497" data-end="1533">
<p data-start="1499" data-end="1533">Removing temporary or test data.</p>
</li>
<li data-start="1534" data-end="1611">
<p data-start="1536" data-end="1611">Deleting records that are no longer needed for business or legal reasons.</p>
</li>
<li data-start="1612" data-end="1660">
<p data-start="1614" data-end="1660">Freeing up storage space in large databases.</p>
</li>
</ul>
<h3 data-start="1662" data-end="1717">8. Can soft-deleted records still affect queries?</h3>
<ul data-start="1718" data-end="1826">
<li data-start="1718" data-end="1784">
<p data-start="1720" data-end="1784">No, by default soft-deleted records are excluded from queries.</p>
</li>
<li data-start="1785" data-end="1826">
<p data-start="1787" data-end="1826">To include them, use <code data-start="1808" data-end="1823">withTrashed()</code>.</p>
</li>
</ul>
<h3 data-start="1828" data-end="1888">9. Does soft deleting a record free up database space?</h3>
<ul data-start="1889" data-end="1969">
<li data-start="1889" data-end="1969">
<p data-start="1891" data-end="1969">No. The record still exists in the database; it only gets marked as deleted.</p>
</li>
</ul>
<h3 data-start="1971" data-end="2050">10. Can I mix soft deletes and permanent deletes in the same application?</h3>
<ul data-start="2051" data-end="2161">
<li data-start="2051" data-end="2161">
<p data-start="2053" data-end="2161">Yes. You can soft delete most records and permanently delete others using <code data-start="2127" data-end="2142">forceDelete()</code> whenever needed.</p>
</li>
</ul>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/okbIZu4UCw2NkZsMrYPtx9Tfe2mcaQnCP0zScs8S.png" type="image/png" length="1233236" />
        <media:content url="https://manamil.dev/storage/uploads/posts/okbIZu4UCw2NkZsMrYPtx9Tfe2mcaQnCP0zScs8S.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 19 Jan 2026 18:28:16 +0000</pubDate>

      
                        <category><![CDATA[Laravel soft deletes]]></category>
                  <category><![CDATA[permanent delete Laravel]]></category>
                  <category><![CDATA[Laravel delete data]]></category>
                  <category><![CDATA[Eloquent soft delete]]></category>
                  <category><![CDATA[restore soft deleted records]]></category>
                  <category><![CDATA[Laravel tutorial]]></category>
                  <category><![CDATA[Laravel database]]></category>
                  </item>
      
    <item>
      <title><![CDATA[How to Check Your Domain&#039;s IP Address | Easy Step-by-Step Guide]]></title>
      <link>https://manamil.dev/blog/website-management/how-to-check-your-domains-ip-address-easy-step-by-step-guide</link>
      <guid isPermaLink="true">https://manamil.dev/blog/website-management/how-to-check-your-domains-ip-address-easy-step-by-step-guide</guid>

      
      <description><![CDATA[
        <p>Learn how to find your domain&#039;s IP address using Command Prompt, Terminal, or online tools. Simple instructions for beginners to locate your website&#039;s IP with ease.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/7cfSGAl5p16Jzf60i3tKCXtWlXGhWOfIrNxJ3Hck.png" alt="How to Check Your Domain&#039;s IP Address | Easy Step-by-Step Guide" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2>How to Check the IP Address of a Domain: A Complete Guide for Ubuntu, Mac, and Online Tools</h2>
<p>When managing a website or troubleshooting DNS issues, one of the most common tasks you'll encounter is checking the IP address of a domain. The IP address allows you to identify the exact location of a website on the internet, which can be crucial for resolving issues related to website access, server configuration, and security. In this guide, we&rsquo;ll show you how to check a domain's IP address on <strong>Ubuntu</strong>, <strong>Mac</strong>, and through <strong>online DNS tools</strong>.</p>
<h2>Why Checking Your Domain IP is Important</h2>
<p>Understanding how to find your domain&rsquo;s IP address is essential for several reasons:</p>
<ol>
<li>
<p><strong>Troubleshooting</strong>: If your website is down, knowing your domain&rsquo;s IP address can help you diagnose the problem &mdash; whether it&rsquo;s a server issue or DNS misconfiguration.</p>
</li>
<li>
<p><strong>Security</strong>: Knowing your domain's IP address allows you to monitor network activity and protect against threats such as DDoS attacks.</p>
</li>
<li>
<p><strong>DNS Records</strong>: To configure your DNS settings properly, you&rsquo;ll need the correct IP address associated with your domain.</p>
</li>
</ol>
<p>Checking your domain's IP is a straightforward process, whether you&rsquo;re on a <strong>Linux-based Ubuntu</strong> system, a <strong>Mac</strong>, or prefer to use online tools. Let&rsquo;s walk through the different methods below.</p>
<h2>How to Check Your Domain IP on Ubuntu</h2>
<p>If you're using <strong>Ubuntu</strong>, the easiest way to check the IP address of a domain is through the <strong>command line</strong>. You can use tools like <code>nslookup</code> or <code>dig</code> to get the IP.</p>
<h4>Using <code>nslookup</code>:</h4>
<ol>
<li>
<p>Open the terminal by pressing <strong>Ctrl+Alt+T</strong>.</p>
</li>
<li>
<p>Type the following command:</p>
<pre><code class="language-bash">nslookup yourdomain.com
</code></pre>
<p>Replace &ldquo;yourdomain.com&rdquo; with the actual domain you want to look up.</p>
</li>
<li>
<p>Press Enter. The terminal will display the domain&rsquo;s IP address under the "Non-authoritative answer" section.</p>
</li>
</ol>
<h4>Using <code>dig</code>:</h4>
<ol>
<li>
<p>Open the terminal.</p>
</li>
<li>
<p>Type the following command:</p>
<pre><code class="language-bash">dig yourdomain.com
</code></pre>
<p>This will provide detailed information, including the IP address of the domain under the "ANSWER SECTION."</p>
</li>
</ol>
<p>For more detailed DNS record lookups on <strong>Ubuntu</strong>, check out our <a href="https://manamil.dev/../../../../blog/website-management/dns-checker-guide-tools-online-services-and-email-check">DNS Checker Guide &amp; Tools</a>.</p>
<h2>How to Check Your Domain IP on Mac</h2>
<p>If you&rsquo;re using a <strong>Mac</strong>, the process is similar to Ubuntu. You can use <strong>Terminal</strong> to check your domain&rsquo;s IP address with <code>nslookup</code> or <code>dig</code>.</p>
<h4>Using <code>nslookup</code> on Mac:</h4>
<ol>
<li>
<p>Open <strong>Terminal</strong> from <strong>Applications &gt; Utilities</strong>.</p>
</li>
<li>
<p>Type the following command:</p>
<pre><code class="language-bash">nslookup yourdomain.com
</code></pre>
<p>Replace &ldquo;yourdomain.com&rdquo; with the domain you want to check.</p>
</li>
<li>
<p>Press Enter. The IP address will be displayed in the output.</p>
</li>
</ol>
<h4>Using <code>dig</code> on Mac:</h4>
<ol>
<li>
<p>Open <strong>Terminal</strong>.</p>
</li>
<li>
<p>Type the following command:</p>
<pre><code class="language-bash">dig yourdomain.com
</code></pre>
</li>
<li>
<p>Press Enter to get detailed DNS records, including the IP address of the domain.</p>
</li>
</ol>
<p>Both <code>nslookup</code> and <code>dig</code> are built-in tools on <strong>Mac</strong>, so you don&rsquo;t need to install anything extra.</p>
<p>For additional DNS record verification, take a look at <span style="text-decoration: underline;"><a href="https://manamil.dev/../../../../blog/website-management/dns-checker-tool-verify-your-dns-records-and-ip-address">DNS Checker Tool to Verify Your DNS Records and IP Address</a>.</span></p>
<h2>How to Use Online Tools to Find Your Domain IP</h2>
<p>If you prefer a simpler and faster approach, online DNS tools like <strong>DNS Checker</strong> can help you quickly find the IP address of your domain without the need for command-line tools.</p>
<h2>Steps to Use DNS Checker:</h2>
<ol>
<li>
<p>Visit a reliable DNS lookup tool like <a href="https://manamil.dev/../../../../tools/dns-checker-tool"><span style="text-decoration: underline;">DNS Checke</span>r</a>.</p>
</li>
<li>
<p>Enter your domain name (e.g., yourdomain.com) into the search bar.</p>
</li>
<li>
<p>Click <strong>Check DNS</strong>. The tool will display the domain's associated IP address.</p>
</li>
</ol>
<p>This is a great option for those who want a quick DNS lookup without using a command-line interface. For more advanced features, explore our <span style="text-decoration: underline;"><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Checker Tool</a>.</span></p>
<p>Online tools provide the benefit of quickly checking multiple DNS records and can be especially useful when you're diagnosing DNS issues across different servers. For more help on DNS troubleshooting, check our post on <span style="text-decoration: underline;"><a href="https://manamil.dev/../../../../blog/website-management/the-ultimate-guide-how-to-fix-dns-server-not-responding-error">How to Fix DNS Server Not Responding Error</a>.</span></p>
<h2>Conclusion</h2>
<p>Whether you're using <strong>Ubuntu</strong>, <strong>Mac</strong>, or an <strong>online DNS tool</strong>, checking your domain&rsquo;s IP address is a crucial step in maintaining your website&rsquo;s performance, security, and troubleshooting DNS issues. By using the methods outlined in this guide, you can quickly find the information you need and ensure that your domain is properly configured.</p>
<p>Remember, staying informed about DNS and domain configurations is essential for keeping your website running smoothly. If you're still uncertain about DNS records, or need to troubleshoot further, check out our comprehensive <span style="text-decoration: underline;"><a href="https://manamil.dev/../../../../blog/website-management/dns-checker-guide-tools-online-services-and-email-check">DNS Checker Guide &amp; Tools</a>.</span></p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/7cfSGAl5p16Jzf60i3tKCXtWlXGhWOfIrNxJ3Hck.png" type="image/png" length="1083189" />
        <media:content url="https://manamil.dev/storage/uploads/posts/7cfSGAl5p16Jzf60i3tKCXtWlXGhWOfIrNxJ3Hck.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 01 Dec 2025 17:48:35 +0000</pubDate>

      
                        <category><![CDATA[Check domain IP]]></category>
                  <category><![CDATA[DNS tools]]></category>
                  <category><![CDATA[Find domain IP]]></category>
                  <category><![CDATA[DNS lookup]]></category>
                  <category><![CDATA[Ubuntu DNS check]]></category>
                  <category><![CDATA[Mac DNS check]]></category>
                  <category><![CDATA[Domain IP lookup tools]]></category>
                  </item>
      
    <item>
      <title><![CDATA[DNS Checker Tool - Verify Your DNS Records and IP Address]]></title>
      <link>https://manamil.dev/blog/website-management/dns-checker-tool-verify-your-dns-records-and-ip-address</link>
      <guid isPermaLink="true">https://manamil.dev/blog/website-management/dns-checker-tool-verify-your-dns-records-and-ip-address</guid>

      
      <description><![CDATA[
        <p>Use our DNS Checker Tool to quickly verify your DNS records and IP address. Ensure optimal website performance and troubleshoot DNS issues with ease.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/0mKIINNyQF6Ok1KO31kQW9WdjNcr63QhjFOO0tEA.jpg" alt="DNS Checker Tool - Verify Your DNS Records and IP Address" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2>Verify Your DNS Records and IP Address with Our DNS Checker Tool</h2>
<p>If you're managing a website, ensuring that your DNS records are correctly configured is crucial for maintaining its performance and availability. With our<a href="https://manamil.dev/../../../tools/dns-checker-tool"> <strong data-start="648" data-end="668">DNS Checker Tool</strong></a>, you can easily verify your DNS records and check your IP address to troubleshoot any issues that may arise.</p>
<h2 data-start="779" data-end="799">What is DNS?</h2>
<p data-start="801" data-end="1152">DNS, or <strong data-start="809" data-end="831">Domain Name System</strong>, is essentially the phonebook of the internet. When you type a website's domain name into your browser, DNS translates that name into an IP address so your browser knows where to find the site. Incorrect or outdated DNS records can cause issues like website downtime, slow loading speeds, or incorrect content delivery.</p>
<h2 data-start="1154" data-end="1191"><strong data-start="1158" data-end="1191">Why Use the DNS Checker Tool?</strong></h2>
<ul>
<li data-start="1195" data-end="1288"><strong data-start="1195" data-end="1218">Verify DNS Records:</strong> Ensure that your DNS records are up-to-date and correctly configured.</li>
<li data-start="1291" data-end="1381"><strong data-start="1291" data-end="1317">Check Your IP Address:</strong> Verify your IP address to troubleshoot any connectivity issues.</li>
<li data-start="1384" data-end="1507"><strong data-start="1384" data-end="1402">Quick Results:</strong> Get instant feedback on the status of your DNS records to avoid any unnecessary delays in fixing issues.</li>
<li data-start="1510" data-end="1633"><strong data-start="1510" data-end="1538">User-Friendly Interface:</strong> Our tool is simple and easy to use, making it accessible to both beginners and advanced users.</li>
</ul>
<h2>How to Use the DNS Checker Tool?</h2>
<ul>
<li data-start="1680" data-end="1762"><strong data-start="1680" data-end="1707">Enter Your Domain Name:</strong> Simply type in your domain name (e.g., <code data-start="1747" data-end="1760">example.com</code>).</li>
<li data-start="1766" data-end="1870"><strong data-start="1766" data-end="1800">Select the Type of DNS Record:</strong> Choose from various DNS records such as A, AAAA, CNAME, MX, TXT, etc.</li>
<li data-start="1874" data-end="1951"><strong data-start="1874" data-end="1892">Run the Check:</strong> Hit the "Check DNS" button and get the results in seconds.</li>
<li data-start="1955" data-end="2051"><strong data-start="1955" data-end="1972">View Results:</strong> The tool will display detailed information on your DNS records and IP address.</li>
</ul>
<h2>Benefits of DNS Checker Tool</h2>
<ul>
<li data-start="2093" data-end="2213"><strong data-start="2093" data-end="2107">Save Time:</strong> Rather than manually checking DNS records across multiple locations, our tool does it for you in seconds.</li>
<li data-start="2216" data-end="2303"><strong data-start="2216" data-end="2229">Accuracy:</strong> Get accurate, up-to-date information to ensure your DNS setup is correct.</li>
<li data-start="2306" data-end="2418"><strong data-start="2306" data-end="2322">Free to Use:</strong> No need to pay for premium services. Our tool is completely free and provides reliable results.</li>
</ul>
<h2 data-start="2420" data-end="2462">Common DNS Issues You Can Identify</h2>
<ul>
<li data-start="2466" data-end="2641"><strong data-start="2466" data-end="2492">DNS Propagation Delay:</strong> It takes time for DNS changes to propagate across the internet. Our tool helps you track how long it will take for these changes to appear globally.</li>
<li data-start="2644" data-end="2792"><strong data-start="2644" data-end="2670">DNS Resolution Errors:</strong> If a DNS record is incorrect or not configured, your website may not load. Use our tool to identify and fix these errors.</li>
<li data-start="2795" data-end="2927"><strong data-start="2795" data-end="2821">IP Address Mismatches:</strong> If your website is pointing to the wrong IP address, use our tool to check and resolve the issue quickly.</li>
</ul>
<h2 data-start="2929" data-end="2947">Conclusion</h2>
<p data-start="2949" data-end="3196">Our <a href="https://manamil.dev/../../../tools/dns-checker-tool"><strong data-start="2953" data-end="2973">DNS Checker Tool</strong></a> is a fast, reliable, and free solution for checking your DNS records and IP address. Whether you&rsquo;re troubleshooting issues or ensuring your website is configured correctly, this tool helps you maintain optimal performance.</p>
<p data-start="3198" data-end="3359">Try it now and get immediate results! For more information, or to explore additional tools, visit <a class="decorated-link" href="https://manamil.dev/../../../tools/dns-checker-tool" target="_new" rel="noopener" data-start="3296" data-end="3358">DNS Checker Tool</a>.</p>
<h2 data-start="3366" data-end="3375">FAQs:</h2>
<ol data-start="3377" data-end="3855">
<li data-start="3377" data-end="3557">
<p data-start="3380" data-end="3557"><strong data-start="3380" data-end="3405">What is a DNS record?</strong><br>A DNS record provides information about a domain, such as its IP address or email servers. It allows users to access your website or email services.</p>
</li>
<li data-start="3559" data-end="3695">
<p data-start="3562" data-end="3695"><strong data-start="3562" data-end="3601">How long does DNS propagation take?</strong><br>DNS changes can take anywhere from a few minutes to 48 hours to fully propagate worldwide.</p>
</li>
<li data-start="3697" data-end="3855">
<p data-start="3700" data-end="3855"><strong data-start="3700" data-end="3748">Why should I check my DNS records regularly?</strong><br>Regular checks ensure your DNS setup is correct, preventing issues like downtime or slow loading times.</p>
</li>
</ol>
<p data-start="3862" data-end="3887"><strong data-start="3862" data-end="3887">Call to Action (CTA):</strong></p>
<p data-start="3889" data-end="4008"><strong data-start="3889" data-end="3903">Need Help?</strong> If you&rsquo;re experiencing DNS issues, use our <a href="https://manamil.dev/../../../../tools/dns-checker-tool"><strong>DNS Checker Tool</strong> </a>now or contact us for more detailed support.</p>
<p data-start="4010" data-end="4112">#DNSChecker #DNSRecords #IPAddress #WebsiteOptimization #WebPerformance #TroubleshootDNS</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/0mKIINNyQF6Ok1KO31kQW9WdjNcr63QhjFOO0tEA.jpg" type="image/jpeg" length="25205" />
        <media:content url="https://manamil.dev/storage/uploads/posts/0mKIINNyQF6Ok1KO31kQW9WdjNcr63QhjFOO0tEA.jpg" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 01 Dec 2025 17:18:19 +0000</pubDate>

      
                        <category><![CDATA[DNSChecker]]></category>
                  <category><![CDATA[DNSRecords]]></category>
                  <category><![CDATA[IPAddress]]></category>
                  <category><![CDATA[WebsiteOptimization]]></category>
                  <category><![CDATA[WebPerformance]]></category>
                  <category><![CDATA[TroubleshootDNS]]></category>
                  </item>
      
    <item>
      <title><![CDATA[The Ultimate Guide: How to Fix &quot;DNS Server Not Responding&quot; Error]]></title>
      <link>https://manamil.dev/blog/website-management/the-ultimate-guide-how-to-fix-dns-server-not-responding-error</link>
      <guid isPermaLink="true">https://manamil.dev/blog/website-management/the-ultimate-guide-how-to-fix-dns-server-not-responding-error</guid>

      
      <description><![CDATA[
        <p>The Ultimate Guide: How to Fix &quot;DNS Server Not Responding&quot; Error</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/G5cnKyCZMMZ3GxU9nKOZR8TiDgdcbtsDqFzeGFpF.png" alt="How to Fix DNS Server Not Responding" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <div id="model-response-message-contentr_e3702d4141c36a24" class="markdown markdown-main-panel stronger enable-updated-hr-color" dir="ltr" aria-live="polite" aria-busy="false">
<h2>The Ultimate Guide: How to Fix "DNS Server Not Responding" Error</h2>
<p data-path-to-node="2">Few error messages are as frustrating as <strong>"DNS Server Not Responding."</strong> It&rsquo;s the digital equivalent of trying to call a business but realizing the phone book entry is wrong&mdash;you know where you want to go, but your device can't translate the name into an address.</p>
<p data-path-to-node="3">This common problem means your device can't connect to the <strong>Domain Name System (DNS)</strong> server, which translates human-readable domain names (like <code>google.com</code>) into computer-readable IP addresses. When it fails, your internet connection stalls.</p>
<p data-path-to-node="4">Fortunately, this issue is rarely catastrophic. In most cases, you can fix it yourself with a few simple steps. Here is the definitive troubleshooting guide, starting with the simplest solutions.</p>
<h2>1. The Quick-Fix Reboot (Always Start Here)</h2>
<p data-path-to-node="6">Before diving into complex settings, try the two easiest methods, which resolve the issue over half the time.</p>
<h3>Restart Your Devices</h3>
<p data-path-to-node="8">Sometimes, a temporary glitch or memory overload causes the error.</p>
<ol start="1" data-path-to-node="9">
<li>
<p data-path-to-node="9,0,0"><strong>Restart Your Computer:</strong> A fresh start can clear up local connection errors.</p>
</li>
<li>
<p data-path-to-node="9,1,0"><strong>Power Cycle Your Router and Modem:</strong> Unplug both your router and your modem from the power source for at least <strong>30 seconds</strong>. This forces them to clear their memory, drop old connections, and reacquire fresh IP and DNS information from your Internet Service Provider (ISP). Plug them back in and wait a couple of minutes for them to fully reboot.</p>
</li>
</ol>
<h3>Test with Another Browser or Device</h3>
<p data-path-to-node="11">If the error persists, check if the issue is limited to your computer or if it&rsquo;s a network-wide problem.</p>
<ul data-path-to-node="12">
<li>
<p data-path-to-node="12,0,0">Try loading a website on a different browser (e.g., if you use Chrome, try Firefox or Edge).</p>
</li>
<li>
<p data-path-to-node="12,1,0">Try connecting on your smartphone or tablet (while connected to your home Wi-Fi).</p>
</li>
</ul>
<p data-path-to-node="13">If only your computer is affected, the problem is likely in your device&rsquo;s local settings. If the error affects all devices, the problem is with your <strong>router, modem, or ISP.</strong></p>
<h2>2. Local System Troubleshooting (PC/Mac)</h2>
<p data-path-to-node="16">If the problem is isolated to your computer, these steps clear out corrupt or outdated local DNS records.</p>
<h3>A. Flush Your DNS Cache</h3>
<p data-path-to-node="18">Your computer keeps a temporary record (cache) of recent DNS translations. If this cache gets corrupted or stores an incorrect address, you'll see the error. Clearing it forces your system to get new, fresh information.</p>
<ul data-path-to-node="19">
<li>
<p data-path-to-node="19,0,0"><strong>For Windows:</strong></p>
<ol start="1" data-path-to-node="19,0,1">
<li>
<p data-path-to-node="19,0,1,0,0">Open the <strong>Command Prompt</strong> as an Administrator.</p>
</li>
<li>
<p data-path-to-node="19,0,1,1,0">Type the command: <code>ipconfig /flushdns</code></p>
</li>
<li>
<p data-path-to-node="19,0,1,2,0">Press Enter. You should see a message: "Successfully flushed the DNS Resolver Cache."</p>
</li>
</ol>
</li>
<li>
<p data-path-to-node="19,1,0"><strong>For Mac:</strong></p>
<ol start="1" data-path-to-node="19,1,1">
<li>
<p data-path-to-node="19,1,1,0,0">Open <strong>Terminal</strong>.</p>
</li>
<li>
<p data-path-to-node="19,1,1,1,0">Type the command: <code>sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder</code></p>
</li>
<li>
<p data-path-to-node="19,1,1,2,0">Press Enter and enter your password.</p>
</li>
</ol>
</li>
</ul>
<h3>B. Renew Your IP Address</h3>
<p data-path-to-node="21">Renewing your IP address forces your computer to communicate with your router and obtain a completely new connection lease, which often fixes DNS issues.</p>
<ul data-path-to-node="22">
<li>
<p data-path-to-node="22,0,0"><strong>For Windows:</strong></p>
<ol start="1" data-path-to-node="22,0,1">
<li>
<p data-path-to-node="22,0,1,0,0">Open the <strong>Command Prompt</strong> as an Administrator.</p>
</li>
<li>
<p data-path-to-node="22,0,1,1,0">Type: <code>ipconfig /release</code> (This releases your current IP).</p>
</li>
<li>
<p data-path-to-node="22,0,1,2,0">Type: <code>ipconfig /renew</code> (This obtains a new IP).</p>
</li>
</ol>
</li>
</ul>
<h2>3. The Ultimate Fix: Change Your DNS Server</h2>
<p data-path-to-node="25">Often, your ISP's default DNS servers are slow or unreliable. Switching to a public, high-speed DNS server is the most effective and long-term fix for this recurring error.</p>
<p data-path-to-node="26">We recommend using services from <strong>Cloudflare</strong> or <strong>Google</strong>.</p>
<table data-path-to-node="27">
<thead>
<tr>
<td><strong>Service</strong></td>
<td><strong>Preferred DNS (IPv4)</strong></td>
<td><strong>Alternate DNS (IPv4)</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td><span data-path-to-node="27,1,0,0"><strong>Cloudflare</strong></span></td>
<td><span data-path-to-node="27,1,1,0"><code>1.1.1.1</code></span></td>
<td><span data-path-to-node="27,1,2,0"><code>1.0.0.1</code></span></td>
</tr>
<tr>
<td><span data-path-to-node="27,2,0,0"><strong>Google Public DNS</strong></span></td>
<td><span data-path-to-node="27,2,1,0"><code>8.8.8.8</code></span></td>
<td><span data-path-to-node="27,2,2,0"><code>8.8.4.4</code></span></td>
</tr>
</tbody>
</table>
<h3>How to Change DNS Settings (Windows 10/11)</h3>
<ol start="1" data-path-to-node="29">
<li>
<p data-path-to-node="29,0,0">Go to <strong>Control Panel</strong> -&gt; <strong>Network and Sharing Center</strong>.</p>
</li>
<li>
<p data-path-to-node="29,1,0">Click <strong>"Change adapter settings"</strong> on the left.</p>
</li>
<li>
<p data-path-to-node="29,2,0">Right-click on your active connection (Wi-Fi or Ethernet) and select <strong>Properties</strong>.</p>
</li>
<li>
<p data-path-to-node="29,3,0">In the new window, find and select <strong>"Internet Protocol Version 4 (TCP/IPv4)"</strong> and click <strong>Properties</strong>.</p>
</li>
<li>
<p data-path-to-node="29,4,0">Select <strong>"Use the following DNS server addresses."</strong></p>
</li>
<li>
<p data-path-to-node="29,5,0">Enter your chosen DNS addresses (e.g., <code>1.1.1.1</code> and <code>1.0.0.1</code>) and click <strong>OK</strong>.</p>
</li>
</ol>
<h2>4. Advanced Network &amp; Security Checks</h2>
<p data-path-to-node="32">If you're still seeing the error, it's time to check your security and network hardware.</p>
<h3>Check Your Firewall and Antivirus</h3>
<p data-path-to-node="34">Overly aggressive security software can mistakenly block outgoing DNS requests, preventing your computer from talking to the DNS server.</p>
<ul data-path-to-node="35">
<li>
<p data-path-to-node="35,0,0"><strong>Temporarily disable your third-party antivirus and firewall</strong> software (e.g., Norton, McAfee, etc.).</p>
</li>
<li>
<p data-path-to-node="35,1,0">Try loading a website. If it works, you know the security program is the culprit. Re-enable the software and look for a setting to allow DNS traffic or make an exception for your browser.</p>
</li>
</ul>
<h3>Reset the Network Stack</h3>
<p data-path-to-node="37">If your system's networking protocols have become corrupt, you may need a full reset.</p>
<ol start="1" data-path-to-node="38">
<li>
<p data-path-to-node="38,0,0">Open the <strong>Command Prompt</strong> as an Administrator.</p>
</li>
<li>
<p data-path-to-node="38,1,0">Run the following commands one by one, pressing Enter after each:</p>
<ul data-path-to-node="38,1,1">
<li>
<p data-path-to-node="38,1,1,0,0"><code>netsh winsock reset</code></p>
</li>
<li>
<p data-path-to-node="38,1,1,1,0"><code>netsh int ip reset</code></p>
</li>
</ul>
</li>
<li>
<p data-path-to-node="38,2,0"><strong>Restart your computer.</strong></p>
</li>
</ol>
<h2>5. Verify and Diagnose Your DNS Health</h2>
<p data-path-to-node="41">Once you've applied these fixes, it's crucial to confirm that your DNS is working correctly. This is where specialized tools come in handy.</p>
<p data-path-to-node="42">If you suspect the problem isn't with your local settings, but perhaps an issue with the domain you are trying to reach, you need a way to check its status globally.</p>
<p data-path-to-node="43">Before concluding the problem is on your end, <strong>run a check</strong> to see how the DNS records for a specific website are resolving around the world. A powerful utility can perform this diagnosis quickly. You can use this <strong><span style="text-decoration: underline;"><a class="ng-star-inserted" href="https://manamil.dev/../../../tools/dns-checker-tool" target="_blank" rel="noopener" data-hveid="0" data-ved="0CAAQ_4QMahgKEwiK8drG64-RAxUAAAAAHQAAAAAQqQE">DNS Checker Tool</a></span></strong> to instantly see if the DNS records for your website, or any website, are propagated correctly.</p>
<p data-path-to-node="44">For a deeper understanding of how these diagnostics work and to troubleshoot domain-specific issues, consult our detailed <strong><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><span style="text-decoration: underline;"><a class="ng-star-inserted" href="https://manamil.dev/../../../../blog/website-management/dns-checker-guide-tools-online-services-and-email-check" target="_blank" rel="noopener" data-hveid="0" data-ved="0CAAQ_4QMahgKEwiK8drG64-RAxUAAAAAHQAAAAAQqgE">DNS Checker Guide: Tools, Online Services, and Email Checks</a></span><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----></strong>. These resources are invaluable for webmasters and users who need comprehensive control over their domain health.</p>
<h2>Conclusion: When to Call the Experts</h2>
<p data-path-to-node="47">If you have tried all the steps above&mdash;rebooted, flushed, renewed, changed your DNS to public servers, and checked your firewall&mdash;and the error persists across all devices on your network, the issue is almost certainly <strong>outside of your home.</strong></p>
<p data-path-to-node="48">It's time to call your Internet Service Provider (ISP). Explain that you have thoroughly troubleshooted your local network (mentioning that you've tried public DNS and power cycling the router) and ask them to check your connection line and their own DNS servers for outages.</p>
<p data-path-to-node="49"><strong>Keep this guide handy</strong>, because while the "DNS Server Not Responding" error is annoying, it&rsquo;s a problem you now have the power to fix. Happy browsing!</p>
</div>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/G5cnKyCZMMZ3GxU9nKOZR8TiDgdcbtsDqFzeGFpF.png" type="image/png" length="1354291" />
        <media:content url="https://manamil.dev/storage/uploads/posts/G5cnKyCZMMZ3GxU9nKOZR8TiDgdcbtsDqFzeGFpF.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Wed, 26 Nov 2025 12:54:47 +0000</pubDate>

      
                        <category><![CDATA[The Ultimate Guide: How to Fix &quot;DNS Server Not Responding&quot; Error]]></category>
                  </item>
      
    <item>
      <title><![CDATA[DNS Checker Guide: Tools, Online Services, and Email Check]]></title>
      <link>https://manamil.dev/blog/website-management/dns-checker-guide-tools-online-services-and-email-check</link>
      <guid isPermaLink="true">https://manamil.dev/blog/website-management/dns-checker-guide-tools-online-services-and-email-check</guid>

      
      <description><![CDATA[
        <p>Discover the best DNS checker tools and online services for Google DNS, global DNS, website DNS, email DNS, and more. Learn how to check IPs, reverse lookup, blacklists, and email headers with ease</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/GmNny9WTJw7irggB6N9uHRQUcXSS5LXcKx2kcOIb.png" alt="DNS Checker Guide: Tools, Online Services, and Email Check" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2>DNS Propagation Checker - A Complete Guide to Tracking DNS Changes Globally</h2>
<p>When you update your DNS records, it&rsquo;s essential to ensure those changes are reflected across the globe. But how do you track this? How can you be sure that your DNS changes are working everywhere? That&rsquo;s where our <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span> comes in.</p>
<p>Our <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Test tool</a></strong></span> simplifies the process of tracking DNS updates by checking the status of your DNS changes on over 100+ global DNS servers. It displays propagation results on a map, allowing you to monitor your DNS records with ease. Whether you&rsquo;re managing a website, setting up new email routing, or handling DNS for a large organization, our tool is here to make your life easier.</p>
<h2>How to Use the DNS Propagation Checker Tool</h2>
<p>Using the <strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool"><span style="text-decoration: underline;">DNS Propagation Checker</span></a></strong> is simple and straightforward. Follow these steps to track your DNS changes:</p>
<ol>
<li>
<p><strong>Enter Your Domain or Hostname:</strong><br>Start by typing the domain or hostname of the website whose DNS you want to check into the <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong>.</span> This will initiate the lookup process across global servers.</p>
</li>
<li>
<p><strong>Select the DNS Record for Status Check:</strong><br>Our tool supports various DNS records, each of which plays a specific role. You can choose from:</p>
<ul>
<li>
<p><strong>A Record</strong>: The IPv4 address of your hostname.</p>
</li>
<li>
<p><strong>AAAA Record</strong>: The IPv6 address of your hostname.</p>
</li>
<li>
<p><strong>CNAME Record</strong>: Alias records that map subdomains to main domains (e.g., www.yourwebsite.com to yourwebsite.com).</p>
</li>
<li>
<p><strong>MX Record</strong>: The mail exchange record, defining mail servers for email routing.</p>
</li>
<li>
<p><strong>NS Record</strong>: The authoritative name servers for the domain.</p>
</li>
<li>
<p><strong>PTR Record</strong>: Used for reverse IP lookups, mapping an IP address back to a domain.</p>
</li>
<li>
<p><strong>SRV Record</strong>: Service records specifying the location of specific services like VoIP or email.</p>
</li>
<li>
<p><strong>SOA Record</strong>: Start of authority, containing the DNS zone information.</p>
</li>
<li>
<p><strong>TXT Record</strong>: Includes configuration information such as SPF or DKIM.</p>
</li>
<li>
<p><strong>CAA Record</strong>: Identifies the certificate authorities allowed to issue SSL certificates for your domain.</p>
</li>
<li>
<p><strong>DS Record</strong>: Used in DNSSEC to maintain the security chain of trust.</p>
</li>
</ul>
</li>
</ol>
<h2>Perform Quick DNS Propagation</h2>
<p>Once you've entered your domain and selected the record, click the &ldquo;Check DNS&rdquo; button on the <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span>. The tool will scan multiple DNS servers globally, displaying results that show whether your DNS change has propagated.</p>
<h3>Visual Results</h3>
<p>The results will be shown on a map. Each server location will be highlighted with a green checkmark or a red cross:</p>
<ul>
<li>
<p><strong>✔️ Green Tick:</strong> DNS records have been successfully propagated to that server.</p>
</li>
<li>
<p><strong>❌ Red Cross:</strong> DNS records have not yet propagated to that server.</p>
</li>
</ul>
<p>If the record matches the updated value, the green tick confirms that the changes are live globally. Conversely, a red cross may indicate that the changes haven&rsquo;t been fully updated, and the server is still seeing the old records.</p>
<h2>Additional Features of the DNS Propagation Checker Tool</h2>
<ul>
<li>
<p><strong>Add a Custom DNS Server:</strong><br>Want to test specific DNS servers? You can easily add a custom DNS server by clicking the &ldquo;+&rdquo; button on the <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span>. You&rsquo;ll need to provide the DNS Name, DNS IP, DNS Provider, and Map Latitude &amp; Longitude for it to be added to the public list.</p>
</li>
<li>
<p><strong>Check Propagation by Region:</strong><br>You can narrow down your search to specific countries, continents, or IP addresses. This way, you can track DNS changes in particular regions where you might be facing issues.</p>
</li>
</ul>
<h2>Understanding DNS Propagation and Why It Takes Time</h2>
<p>When you update DNS records, these changes must propagate across multiple DNS servers globally. DNS propagation refers to the time it takes for these changes to be reflected everywhere. This process can take up to 48 hours, though in many cases, it can be faster.</p>
<p>Several factors contribute to this delay:</p>
<ul>
<li>
<p><strong>Cache Levels:</strong> Different DNS servers cache DNS records for varying amounts of time, meaning some users might still see the old DNS records even after you&rsquo;ve made changes.</p>
</li>
<li>
<p><strong>Geographic Spread:</strong> DNS servers in different regions around the world update at different times, causing discrepancies in the DNS records seen by users.</p>
</li>
<li>
<p><strong>TTL (Time to Live):</strong> Each DNS record has a TTL value that tells DNS servers how long to cache the record. A lower TTL can help propagate changes faster.</p>
</li>
</ul>
<h2>Why DNS Changes Might Not Be Propagating</h2>
<p>If DNS changes are taking longer than expected, it could be due to a few reasons:</p>
<ul>
<li>
<p><strong>Old DNS Information Cached:</strong> Some ISPs or DNS resolvers may still be using the cached DNS information, which can delay the propagation process.</p>
</li>
<li>
<p><strong>DNS Servers Not Updated:</strong> If certain DNS servers haven&rsquo;t been updated with the new records, you&rsquo;ll see a delay in the propagation. The <strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong> tool can help diagnose and fix these issues.</p>
</li>
<li>
<p><strong>TTL Settings:</strong> If you recently updated your DNS records and the TTL hasn&rsquo;t expired yet, users might still see the old records until the TTL period finishes.</p>
</li>
</ul>
<h2>Common DNS Issues and How to Fix Them</h2>
<ul>
<li>
<p><strong>DNS Failure:</strong><br>If the DNS server can&rsquo;t resolve the domain name to an IP address, it results in a DNS failure. This could be due to incorrect DNS settings or issues with the DNS server.</p>
</li>
<li>
<p><strong>DNS Not Propagating Properly:</strong><br>If DNS changes are taking longer than expected, it could be due to outdated cache or misconfigured DNS settings. You can try flushing your DNS cache or performing a DNS health check.</p>
</li>
<li>
<p><strong>Domain Not Found:</strong><br>If a domain name doesn&rsquo;t exist in the DNS records, you&rsquo;ll get an NXDomain response.</p>
</li>
</ul>
<p>The <span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span> is the perfect tool to help identify and resolve these issues.</p>
<h2>The Best DNS Servers to Use for Optimal Performance</h2>
<p>Choosing the right DNS server can improve your browsing experience. Here are some of the best public DNS servers you can use:</p>
<ul>
<li>
<p><strong>Google Public DNS:</strong><br>IPv4: 8.8.8.8 (Primary), 8.8.4.4 (Secondary)<br>IPv6: 2001:4860:4860::8888 (Primary), 2001:4860:4860::8844 (Secondary)</p>
</li>
<li>
<p><strong>Cloudflare DNS:</strong><br>IPv4: 1.1.1.1 (Primary), 1.0.0.1 (Secondary)<br>IPv6: 2606:4700:4700::1111 (Primary), 2606:4700:4700::1001 (Secondary)</p>
</li>
<li>
<p><strong>OpenDNS:</strong><br>IPv4: 208.67.222.222 (Primary), 208.67.220.220 (Secondary)</p>
</li>
<li>
<p><strong>Quad9 (For malware blocking):</strong><br>IPv4: 9.9.9.9 (Primary), 149.112.112.112 (Secondary)</p>
</li>
</ul>
<p>By using the&nbsp;<span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span> tool, you can efficiently track and troubleshoot DNS updates, ensuring your changes are successfully reflected across the globe.</p>
<p>Feel free to replace or modify any sections according to your preferences. This version naturally integrates the internal link to the&nbsp;<span style="text-decoration: underline;"><strong><a href="https://manamil.dev/../../../../tools/dns-checker-tool">DNS Propagation Checker</a></strong></span> throughout the article.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/GmNny9WTJw7irggB6N9uHRQUcXSS5LXcKx2kcOIb.png" type="image/png" length="1690703" />
        <media:content url="https://manamil.dev/storage/uploads/posts/GmNny9WTJw7irggB6N9uHRQUcXSS5LXcKx2kcOIb.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Wed, 26 Nov 2025 08:39:55 +0000</pubDate>

      
              <category><![CDATA[Website Management]]></category>
          </item>
      
    <item>
      <title><![CDATA[12 Python Scripts to Automate Tasks &amp; Save Hours Daily]]></title>
      <link>https://manamil.dev/blog/python/12-python-scripts-to-automate-tasks-save-hours-daily</link>
      <guid isPermaLink="true">https://manamil.dev/blog/python/12-python-scripts-to-automate-tasks-save-hours-daily</guid>

      
      <description><![CDATA[
        <p>Boost your productivity with 12 simple yet powerful Python scripts. Learn how to automate file management, emails, data entry, and more. Start saving time today!</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/BZ7Q2cEvNy1Mk5YEQ7y2wRyPq5Vero5Zasq7bOMM.png" alt="12 Python Scripts to Automate Tasks &amp; Save Hours Daily" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <div id="model-response-message-contentr_c277e8e5335dac42" class="markdown markdown-main-panel enable-updated-hr-color" dir="ltr" aria-live="polite" aria-busy="false">
<h1>12 Python Scripts to Automate Tasks &amp; Save Hours Daily</h1>
<p>Hey everyone! As a developer, I spend my life seeking efficiency. We all know Python is the Swiss Army knife of scripting, but sometimes the "12 scripts to rename your downloads" lists just don't cut it. We need <em>real</em> power. We need automations that tackle the tedious, the complex, and the truly time-consuming tasks that crop up daily, especially in a professional setting.</p>
<p>I've put together a list of 12 highly practical, copy-paste-ready Python scripts that I actually use to shave <strong>hours</strong> off my workflow every single week. These aren't just file organizers; these are scripts that dive into system resources, handle asynchronous data, and manipulate files at a deep level.</p>
<p>Ready to level up your productivity? Let's dive in. 🚀</p>
<h2>1. The Clipboard Rule Engine: Your Text Transformation Butler</h2>
<h3>Problem Solved</h3>
<p>How often do you copy a URL only to realize you need to strip the tracking parameters? Or maybe you copy a Python function name and need it in snake_case for your documentation? Manual reformatting is a massive time sink.</p>
<h3>Solution Overview</h3>
<p>This script runs in the background, monitors your clipboard, and applies a set of user-defined Regular Expression (RegEx) rules. If a rule matches the copied text, it automatically replaces it with the transformed output. Think of it as IFTTT for your clipboard.</p>
<h3>The Code</h3>
<!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c1877124198-68 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQyQI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-68">
<div class="animated-opacity ng-tns-c1877124198-68">
<pre class="ng-tns-c1877124198-68"><code class="code-container formatted ng-tns-c1877124198-68" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> pyperclip
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> time

RULES = [
    <span class="hljs-comment"># 1. Clean Google/Affiliate Tracking URLs</span>
    (re.<span class="hljs-built_in">compile</span>(<span class="hljs-string">r'(\?|&amp;)(utm_.*?|aff_.*?|ref=.*?)=[^&amp;]*'</span>), <span class="hljs-string">''</span>),
    
    <span class="hljs-comment"># 2. Convert PascalCase to snake_case</span>
    (re.<span class="hljs-built_in">compile</span>(<span class="hljs-string">r'(.)([A-Z][a-z]+)'</span>), <span class="hljs-string">r'\1_\2'</span>),
    (re.<span class="hljs-built_in">compile</span>(<span class="hljs-string">r'([a-z0-9])([A-Z])'</span>), <span class="hljs-string">r'\1_\2'</span>)
]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_rules</span>(<span class="hljs-params">text</span>):</span>
    <span class="hljs-keyword">for</span> pattern, replacement <span class="hljs-keyword">in</span> RULES:
        text = pattern.sub(replacement, text).lower()
    <span class="hljs-keyword">return</span> text

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    recent_value = pyperclip.paste()
    print(<span class="hljs-string">"Clipboard Engine running... Press Ctrl+C to stop."</span>)
    
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">try</span>:
            current_value = pyperclip.paste()
            <span class="hljs-keyword">if</span> current_value != recent_value:
                transformed_value = apply_rules(current_value)
                
                <span class="hljs-keyword">if</span> transformed_value != current_value:
                    print(<span class="hljs-string">f"Clipboard updated. Original: '<span class="hljs-subst">{current_value[:<span class="hljs-number">30</span>]}</span>...' -&gt; New: '<span class="hljs-subst">{transformed_value[:<span class="hljs-number">30</span>]}</span>...'"</span>)
                    pyperclip.copy(transformed_value)
                
                recent_value = pyperclip.paste() <span class="hljs-comment"># Update with the potentially new value</span>
            time.sleep(<span class="hljs-number">0.5</span>)
        <span class="hljs-keyword">except</span> KeyboardInterrupt:
            <span class="hljs-keyword">break</span>
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This script uses the awesome <strong><code>pyperclip</code></strong> library (you might need <code>pip install pyperclip</code>) to access the system clipboard. It runs an infinite loop, checking the clipboard every 0.5 seconds.</p>
<p>The <code>RULES</code> list holds pairs of <code>(RegEx_Pattern, Replacement_String)</code>. The magic happens when we find a new value; we apply the transformations, and if the output is different, we write it back to the clipboard. I use the URL cleaning rule daily when sharing links&mdash;it keeps URLs short and clean!</p>
<h2>2. Zero-Copy File Transfer via <code>mmap</code></h2>
<h3>Problem Solved</h3>
<p>Copying a very large file (e.g., a 10GB dataset or log file) using standard Python I/O (<code>.read()/.write()</code>) is slow because the OS has to copy the data <strong>twice</strong>: first from disk to OS kernel buffer, and then from the kernel buffer to the Python user-space buffer.</p>
<h3>Solution Overview</h3>
<p>The <strong><code>mmap</code></strong> module allows us to map a file directly into the process's memory space. This drastically reduces the overhead, effectively creating a "zero-copy" operation for copying data streams, which is a huge win for massive files.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-69 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQygI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-69">
<div class="animated-opacity ng-tns-c1877124198-69">
<pre class="ng-tns-c1877124198-69"><code class="code-container formatted ng-tns-c1877124198-69" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> mmap
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> shutil

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">zero_copy_transfer</span>(<span class="hljs-params">source_path, dest_path</span>):</span>
    <span class="hljs-string">"""Copies a file using memory mapping for speed."""</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(source_path):
        print(<span class="hljs-string">f"Error: Source file not found at <span class="hljs-subst">{source_path}</span>"</span>)
        <span class="hljs-keyword">return</span>

    <span class="hljs-comment"># Use shutil.copyfile if the file is small (mmap overhead isn't worth it)</span>
    file_size = os.path.getsize(source_path)
    <span class="hljs-keyword">if</span> file_size &lt; <span class="hljs-number">1024</span> * <span class="hljs-number">1024</span> * <span class="hljs-number">5</span>:  <span class="hljs-comment"># 5 MB threshold</span>
        shutil.copyfile(source_path, dest_path)
        print(<span class="hljs-string">f"Standard copy used for small file: <span class="hljs-subst">{source_path}</span>"</span>)
        <span class="hljs-keyword">return</span>

    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(source_path, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> f_in, <span class="hljs-built_in">open</span>(dest_path, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> f_out:
            <span class="hljs-comment"># Resize the output file to the same size as the input file</span>
            f_out.truncate(file_size) 
            
            <span class="hljs-comment"># Map the file into memory</span>
            <span class="hljs-keyword">with</span> mmap.mmap(f_out.fileno(), file_size, access=mmap.ACCESS_WRITE) <span class="hljs-keyword">as</span> m:
                <span class="hljs-comment"># Read the source data directly into the memory-mapped object</span>
                data = f_in.read()
                m.write(data)
                m.flush()
        
        print(<span class="hljs-string">f"Zero-copy transfer complete: <span class="hljs-subst">{source_path}</span> -&gt; <span class="hljs-subst">{dest_path}</span>"</span>)
        
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"An error occurred: <span class="hljs-subst">{e}</span>"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># Replace these paths with your large file test</span>
    SOURCE = <span class="hljs-string">'large_log_file.txt'</span>  
    DEST = <span class="hljs-string">'large_log_file_copy.txt'</span> 
    
    <span class="hljs-comment"># <span class="hljs-doctag">NOTE:</span> You need a large file at SOURCE path to test this effectively</span>
    <span class="hljs-comment"># You might want to create a dummy 100MB file first!</span>
    
    <span class="hljs-comment"># zero_copy_transfer(SOURCE, DEST)</span>
    print(<span class="hljs-string">"Script ready. Replace file names and uncomment 'zero_copy_transfer' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>We open both source and destination files. The key step is <code>f_out.truncate(file_size)</code> which pre-allocates the space for the destination file. Then, <strong><code>mmap.mmap(f_out.fileno(), file_size, access=mmap.ACCESS_WRITE)</code></strong> maps the output file's underlying physical disk space into our process's virtual memory. When we call <code>m.write(data)</code>, Python essentially copies the data from the source file stream directly to this mapped memory, bypassing the need for temporary buffers, making it lightning fast for huge files. This is essential for moving large database dumps or video assets.</p>
<h2>3. Incremental Hardlink Backups</h2>
<h3>Problem Solved</h3>
<p>Traditional backups waste disk space by creating a full copy every time. But if you only use simple syncing (like <code>rsync</code>), you lose the version history. We need the space efficiency of syncing <em>and</em> the safety of versioning.</p>
<h3>Solution Overview</h3>
<p>This script creates <strong>daily snapshots</strong> using <strong>hardlinks</strong>. A hardlink is a second entry in the file system for the same file data. When the script runs, it creates a new snapshot folder. It hardlinks the files that <strong>haven't changed</strong> since the last backup (zero space used!) and physically copies only the files that <strong>have changed</strong>.</p>
<h3>The Code</h3>
<!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c1877124198-70 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQywI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-70">
<div class="animated-opacity ng-tns-c1877124198-70">
<pre class="ng-tns-c1877124198-70"><code class="code-container formatted ng-tns-c1877124198-70" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">import</span> shutil

SOURCE_DIR = <span class="hljs-string">'/path/to/your/important/data'</span>  <span class="hljs-comment"># &lt;-- CHANGE THIS</span>
BACKUP_ROOT = <span class="hljs-string">'/path/to/your/backup/drive'</span>    <span class="hljs-comment"># &lt;-- CHANGE THIS</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_last_snapshot</span>(<span class="hljs-params">root_dir</span>):</span>
    <span class="hljs-string">"""Finds the path to the most recent daily snapshot."""</span>
    snapshots = [d <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> os.listdir(root_dir) <span class="hljs-keyword">if</span> os.path.isdir(os.path.join(root_dir, d))]
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> snapshots:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    snapshots.sort(reverse=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> os.path.join(root_dir, snapshots[<span class="hljs-number">0</span>])

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run_hardlink_backup</span>():</span>
    timestamp = datetime.datetime.now().strftime(<span class="hljs-string">"%Y-%m-%d_%H%M%S"</span>)
    new_snapshot_dir = os.path.join(BACKUP_ROOT, timestamp)
    
    last_snapshot_dir = get_last_snapshot(BACKUP_ROOT)
    
    print(<span class="hljs-string">f"Creating new snapshot: <span class="hljs-subst">{new_snapshot_dir}</span>"</span>)
    os.makedirs(new_snapshot_dir, exist_ok=<span class="hljs-literal">True</span>)
    
    <span class="hljs-comment"># 1. Hardlink all unchanged files from the last snapshot</span>
    <span class="hljs-keyword">if</span> last_snapshot_dir:
        <span class="hljs-keyword">for</span> root, _, files <span class="hljs-keyword">in</span> os.walk(last_snapshot_dir):
            relative_path = os.path.relpath(root, last_snapshot_dir)
            target_root = os.path.join(new_snapshot_dir, relative_path)
            os.makedirs(target_root, exist_ok=<span class="hljs-literal">True</span>)
            
            <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files:
                src_file = os.path.join(root, file)
                dest_file = os.path.join(target_root, file)
                <span class="hljs-keyword">try</span>:
                    <span class="hljs-comment"># Skip if the source file doesn't exist anymore</span>
                    <span class="hljs-keyword">if</span> os.path.exists(os.path.join(SOURCE_DIR, relative_path, file)):
                        os.link(src_file, dest_file)
                <span class="hljs-keyword">except</span> Exception:
                    <span class="hljs-keyword">pass</span> <span class="hljs-comment"># Ignore errors for now</span>

    <span class="hljs-comment"># 2. Copy/Overwrite changed files from the SOURCE_DIR</span>
    <span class="hljs-keyword">for</span> root, dirs, files <span class="hljs-keyword">in</span> os.walk(SOURCE_DIR):
        relative_path = os.path.relpath(root, SOURCE_DIR)
        target_root = os.path.join(new_snapshot_dir, relative_path)
        os.makedirs(target_root, exist_ok=<span class="hljs-literal">True</span>)
        
        <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files:
            src_file = os.path.join(root, file)
            dest_file = os.path.join(target_root, file)
            
            <span class="hljs-comment"># Check if file has changed (simple check: size/mod time comparison)</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> last_snapshot_dir <span class="hljs-keyword">or</span> \
               <span class="hljs-keyword">not</span> os.path.exists(os.path.join(last_snapshot_dir, relative_path, file)) <span class="hljs-keyword">or</span> \
               os.path.getmtime(src_file) &gt; os.path.getmtime(os.path.join(last_snapshot_dir, relative_path, file)):
                
                print(<span class="hljs-string">f"Copying (changed/new): <span class="hljs-subst">{file}</span>"</span>)
                shutil.copy2(src_file, dest_file) <span class="hljs-comment"># copy2 preserves metadata</span>
            <span class="hljs-comment"># Else: File already hardlinked from step 1</span>

    print(<span class="hljs-string">"Backup finished."</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># IMPORTANT: Update SOURCE_DIR and BACKUP_ROOT paths</span>
    <span class="hljs-comment"># run_hardlink_backup()</span>
    print(<span class="hljs-string">"Script ready. Please update paths and uncomment 'run_hardlink_backup' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This script relies on <code>os.link()</code>, which creates a hardlink. <strong>Hardlinks only work within the same disk/partition.</strong> The core logic is:</p>
<ol start="1">
<li>
<p>Find the path of the last backup (<code>get_last_snapshot</code>).</p>
</li>
<li>
<p>Create the new snapshot folder.</p>
</li>
<li>
<p>Walk the <em>last</em> snapshot and hardlink everything to the <em>new</em> snapshot. (This is fast and uses no extra space.)</p>
</li>
<li>
<p>Walk the <em>source</em> data. If a file is new or has a newer modification time (<code>os.path.getmtime</code>), copy it over the hardlink in the new snapshot, overwriting it.</p>
</li>
</ol>
<p>This is a fantastic automation to run via <strong>Cron</strong> or <strong>Windows Task Scheduler</strong> for true, space-efficient, versioned local backups.</p>
<h2>4. Auto-Detect Broken Links in Local Markdown Docs</h2>
<h3>Problem Solved</h3>
<p>If you manage a documentation site, a large README, or local knowledge base built with Markdown, broken internal or external links are a constant headache. Manual checking is impossible.</p>
<h3>Solution Overview</h3>
<p>This script scans all Markdown files in a directory, extracts all <code>[text](link)</code> patterns, and then checks the validity of each link. It uses standard file checks for internal links and the <code>requests</code> library for external URLs.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-71 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQzAI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-71">
<div class="animated-opacity ng-tns-c1877124198-71">
<pre class="ng-tns-c1877124198-71"><code class="code-container formatted ng-tns-c1877124198-71" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> requests

DOCS_DIR = <span class="hljs-string">'./docs'</span> <span class="hljs-comment"># &lt;-- CHANGE THIS to your docs folder</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_link</span>(<span class="hljs-params">link, base_path</span>):</span>
    <span class="hljs-string">"""Checks if a link is valid (local file or external URL)."""</span>
    <span class="hljs-keyword">if</span> link.startswith(<span class="hljs-string">'http'</span>):
        <span class="hljs-comment"># External link check</span>
        <span class="hljs-keyword">try</span>:
            response = requests.head(link, timeout=<span class="hljs-number">5</span>, allow_redirects=<span class="hljs-literal">True</span>)
            <span class="hljs-keyword">if</span> response.status_code &gt;= <span class="hljs-number">400</span>:
                <span class="hljs-keyword">return</span> <span class="hljs-string">f"External link broken: Status <span class="hljs-subst">{response.status_code}</span>"</span>
            <span class="hljs-keyword">return</span> <span class="hljs-string">"OK"</span>
        <span class="hljs-keyword">except</span> requests.RequestException <span class="hljs-keyword">as</span> e:
            <span class="hljs-keyword">return</span> <span class="hljs-string">f"External link failed: <span class="hljs-subst">{e.__class__.__name__}</span>"</span>
    <span class="hljs-keyword">elif</span> link.startswith(<span class="hljs-string">'#'</span>):
        <span class="hljs-comment"># Anchor links are tricky to validate robustly, skipping for simplicity</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Anchor (SKIPPED)"</span> 
    <span class="hljs-keyword">else</span>:
        <span class="hljs-comment"># Local file check</span>
        full_path = os.path.join(os.path.dirname(base_path), link)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(full_path):
            <span class="hljs-comment"># Check if it's an absolute path from DOCS_DIR root</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(os.path.join(DOCS_DIR, link)):
                 <span class="hljs-keyword">return</span> <span class="hljs-string">f"Local file missing: <span class="hljs-subst">{full_path}</span>"</span>
            
        <span class="hljs-keyword">return</span> <span class="hljs-string">"OK"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_and_check_links</span>():</span>
    <span class="hljs-comment"># RegEx to find Markdown links: [text](link)</span>
    LINK_REGEX = re.<span class="hljs-built_in">compile</span>(<span class="hljs-string">r'\[.*?\]\((.*?)\)'</span>) 
    
    print(<span class="hljs-string">f"Scanning for links in <span class="hljs-subst">{DOCS_DIR}</span>..."</span>)
    broken_links = <span class="hljs-number">0</span>

    <span class="hljs-keyword">for</span> root, _, files <span class="hljs-keyword">in</span> os.walk(DOCS_DIR):
        <span class="hljs-keyword">for</span> file_name <span class="hljs-keyword">in</span> files:
            <span class="hljs-keyword">if</span> file_name.endswith(<span class="hljs-string">'.md'</span>):
                file_path = os.path.join(root, file_name)
                <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(file_path, <span class="hljs-string">'r'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> f:
                    content = f.read()
                    
                    <span class="hljs-keyword">for</span> match <span class="hljs-keyword">in</span> LINK_REGEX.finditer(content):
                        link = match.group(<span class="hljs-number">1</span>).split()[<span class="hljs-number">0</span>] <span class="hljs-comment"># Take link, ignore optional title</span>
                        result = check_link(link, file_path)
                        
                        <span class="hljs-keyword">if</span> result != <span class="hljs-string">"OK"</span> <span class="hljs-keyword">and</span> <span class="hljs-string">"SKIPPED"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> result:
                            broken_links += <span class="hljs-number">1</span>
                            print(<span class="hljs-string">f"[🚨 BROKEN] File: <span class="hljs-subst">{file_path}</span>, Link: <span class="hljs-subst">{link}</span>, Reason: <span class="hljs-subst">{result}</span>"</span>)

    <span class="hljs-keyword">if</span> broken_links == <span class="hljs-number">0</span>:
        print(<span class="hljs-string">"\n✅ All links seem fine!"</span>)
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">f"\n❌ Found <span class="hljs-subst">{broken_links}</span> broken links."</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># You need the 'requests' library: pip install requests</span>
    <span class="hljs-comment"># find_and_check_links()</span>
    print(<span class="hljs-string">"Script ready. Update DOCS_DIR and uncomment 'find_and_check_links' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This script requires the <strong><code>requests</code></strong> library. We use <code>os.walk</code> to find all <code>.md</code> files. The RegEx <code>r'\[.*?\]\((.*?)\)'</code> grabs the URL within the parentheses. The <code>check_link</code> function distinguishes between local file paths (using <code>os.path.exists</code>) and external URLs (using <code>requests.head</code> to check the status code without downloading the entire page). Running this before every documentation deployment is a massive quality-of-life improvement.</p>
<h2>5. Email Triage via IMAP IDLE (Real-time Email Notifications)</h2>
<h3>Problem Solved</h3>
<p>Polling your mailbox every few minutes to check for urgent emails is inefficient and slow. For true real-time email triage without constantly checking a browser tab, we need a better method.</p>
<h3>Solution Overview</h3>
<p>The <strong>IMAP IDLE</strong> command allows a client (our Python script) to instruct the server (like Gmail) to notify it immediately when a change (like a new email) occurs in a monitored folder. This is a low-latency, low-resource way to check for highly specific, urgent emails (e.g., "Deployment Failed").</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-72 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQzQI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-72">
<div class="animated-opacity ng-tns-c1877124198-72">
<pre class="ng-tns-c1877124198-72"><code class="code-container formatted ng-tns-c1877124198-72" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> imaplib
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> re

<span class="hljs-comment"># --- CONFIGURATION ---</span>
IMAP_SERVER = <span class="hljs-string">'imap.gmail.com'</span>
EMAIL_ADDRESS = <span class="hljs-string">'your_email@gmail.com'</span> <span class="hljs-comment"># &lt;-- CHANGE THIS</span>
PASSWORD = <span class="hljs-string">'your_app_password'</span>         <span class="hljs-comment"># &lt;-- CHANGE THIS (Use App Password for Gmail)</span>
MONITOR_FOLDER = <span class="hljs-string">'INBOX'</span>
URGENT_REGEX = re.<span class="hljs-built_in">compile</span>(<span class="hljs-string">r'(failed|alert|critical|deploy|error)'</span>, re.IGNORECASE)
<span class="hljs-comment"># ---------------------</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">imap_idle_triage</span>():</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Connect and Login</span>
        mail = imaplib.IMAP4_SSL(IMAP_SERVER)
        mail.login(EMAIL_ADDRESS, PASSWORD)
        mail.select(MONITOR_FOLDER)
        print(<span class="hljs-string">f"Logged in and monitoring <span class="hljs-subst">{MONITOR_FOLDER}</span> using IDLE..."</span>)

        <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
            <span class="hljs-comment"># Send IDLE command</span>
            mail.send(<span class="hljs-string">b'A001 IDLE\r\n'</span>)
            
            <span class="hljs-comment"># Wait for the server to send a response (new data or timeout)</span>
            response = mail.readline()
            
            <span class="hljs-comment"># If the server responds with an update (like EXISTS or RECENT)</span>
            <span class="hljs-keyword">if</span> <span class="hljs-string">b'OK'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> response:
                print(<span class="hljs-string">"\nNew mail activity detected!"</span>)
                mail.send(<span class="hljs-string">b'DONE\r\n'</span>) <span class="hljs-comment"># Stop IDLE command</span>
                mail.readline()      <span class="hljs-comment"># Consume server response</span>
                
                <span class="hljs-comment"># Check for new, urgent emails</span>
                status, messages = mail.search(<span class="hljs-literal">None</span>, <span class="hljs-string">'UNSEEN'</span>)
                
                <span class="hljs-keyword">if</span> status == <span class="hljs-string">'OK'</span>:
                    <span class="hljs-keyword">for</span> msg_id <span class="hljs-keyword">in</span> messages[<span class="hljs-number">0</span>].split():
                        <span class="hljs-comment"># Fetch the Envelope/Subject only</span>
                        status, data = mail.fetch(msg_id, <span class="hljs-string">'(ENVELOPE)'</span>)
                        
                        <span class="hljs-keyword">if</span> status == <span class="hljs-string">'OK'</span>:
                            envelope_data = data[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>].decode(<span class="hljs-string">'utf-8'</span>)
                            <span class="hljs-comment"># Simple extraction of the subject line from the envelope data (complex regex needed for full robust extraction)</span>
                            subject_match = re.search(<span class="hljs-string">r'"([^"]*)"'</span>, envelope_data) 
                            subject = subject_match.group(<span class="hljs-number">1</span>) <span class="hljs-keyword">if</span> subject_match <span class="hljs-keyword">else</span> <span class="hljs-string">"[Subject Not Found]"</span>

                            <span class="hljs-keyword">if</span> URGENT_REGEX.search(subject):
                                print(<span class="hljs-string">f"🚨 URGENT EMAIL: <span class="hljs-subst">{subject}</span>"</span>)
                                <span class="hljs-comment"># Add code here to trigger a system notification or a text message</span>
                            <span class="hljs-keyword">else</span>:
                                print(<span class="hljs-string">f"New email: <span class="hljs-subst">{subject}</span>"</span>)
                                
                    mail.select(MONITOR_FOLDER) <span class="hljs-comment"># Reselect the folder</span>
            
            time.sleep(<span class="hljs-number">1</span>) <span class="hljs-comment"># Small pause before next IDLE check/loop</span>

    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"IMAP IDLE error: <span class="hljs-subst">{e}</span>"</span>)
    <span class="hljs-keyword">finally</span>:
        <span class="hljs-keyword">try</span>:
            mail.logout()
        <span class="hljs-keyword">except</span>:
            <span class="hljs-keyword">pass</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># IMPORTANT: Update configurations and use an App Password for secure login</span>
    <span class="hljs-comment"># imap_idle_triage()</span>
    print(<span class="hljs-string">"Script ready. Update config and uncomment 'imap_idle_triage' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This is a more advanced script. You <strong>must</strong> use an <strong>App Password</strong> (not your regular account password) for services like Gmail. We connect, select the folder, and send the <strong><code>IDLE</code></strong> command. The script then waits (<code>mail.readline()</code>) until the server pushes a response. When activity is detected, we stop the IDLE (<code>DONE</code>), search for <code>UNSEEN</code> messages, and check their subject against our <code>URGENT_REGEX</code>. This is priceless for DevOps engineers or anyone needing immediate alerts on server failures or critical system health checks.</p>
<h2>6. OCR + Full-Text Search for Screenshots</h2>
<h3>Problem Solved</h3>
<p>Screenshots contain valuable text (error messages, code snippets, meeting notes) that is inaccessible to your system's search bar. Finding that one old screenshot is a nightmare.</p>
<h3>Solution Overview</h3>
<p>This script processes a directory of screenshots, uses an <strong>Optical Character Recognition (OCR)</strong> tool (like Tesseract, via the <code>pytesseract</code> library) to extract all text, and stores the text in a simple SQLite database alongside the file path. You can then query the database for any text found in any of your images.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-73 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQzgI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-73">
<div class="animated-opacity ng-tns-c1877124198-73">
<pre class="ng-tns-c1877124198-73"><code class="code-container formatted ng-tns-c1877124198-73" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> sqlite3
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image
<span class="hljs-keyword">import</span> pytesseract <span class="hljs-comment"># pip install pytesseract, and install Tesseract-OCR engine separately!</span>

SCREENSHOTS_DIR = <span class="hljs-string">'./screenshots'</span> <span class="hljs-comment"># &lt;-- CHANGE THIS</span>
DB_PATH = <span class="hljs-string">'ocr_index.db'</span>
IMAGE_EXTENSIONS = (<span class="hljs-string">'.png'</span>, <span class="hljs-string">'.jpg'</span>, <span class="hljs-string">'.jpeg'</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_db</span>(<span class="hljs-params">conn</span>):</span>
    cursor = conn.cursor()
    cursor.execute(<span class="hljs-string">"""
        CREATE TABLE IF NOT EXISTS ocr_data (
            filepath TEXT PRIMARY KEY,
            ocr_text TEXT,
            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    """</span>)
    conn.commit()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_screenshots</span>():</span>
    conn = sqlite3.connect(DB_PATH)
    create_db(conn)
    cursor = conn.cursor()

    <span class="hljs-keyword">for</span> root, _, files <span class="hljs-keyword">in</span> os.walk(SCREENSHOTS_DIR):
        <span class="hljs-keyword">for</span> file_name <span class="hljs-keyword">in</span> files:
            <span class="hljs-keyword">if</span> file_name.lower().endswith(IMAGE_EXTENSIONS):
                file_path = os.path.join(root, file_name)
                
                <span class="hljs-comment"># Check if already indexed</span>
                cursor.execute(<span class="hljs-string">"SELECT filepath FROM ocr_data WHERE filepath = ?"</span>, (file_path,))
                <span class="hljs-keyword">if</span> cursor.fetchone():
                    <span class="hljs-keyword">continue</span>

                <span class="hljs-keyword">try</span>:
                    <span class="hljs-comment"># OCR process</span>
                    text = pytesseract.image_to_string(Image.<span class="hljs-built_in">open</span>(file_path))
                    
                    <span class="hljs-comment"># Store data</span>
                    cursor.execute(<span class="hljs-string">"INSERT INTO ocr_data (filepath, ocr_text) VALUES (?, ?)"</span>, 
                                   (file_path, text))
                    conn.commit()
                    print(<span class="hljs-string">f"Indexed: <span class="hljs-subst">{file_name}</span>"</span>)
                <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
                    print(<span class="hljs-string">f"Could not process <span class="hljs-subst">{file_name}</span>: <span class="hljs-subst">{e}</span>"</span>)

    conn.close()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search_screenshots</span>(<span class="hljs-params">query</span>):</span>
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    
    <span class="hljs-comment"># Use LIKE for simple full-text search</span>
    cursor.execute(<span class="hljs-string">"SELECT filepath, ocr_text FROM ocr_data WHERE ocr_text LIKE ?"</span>, (<span class="hljs-string">f'%<span class="hljs-subst">{query}</span>%'</span>,))
    results = cursor.fetchall()
    conn.close()
    
    <span class="hljs-keyword">if</span> results:
        print(<span class="hljs-string">f"\n--- Found <span class="hljs-subst">{<span class="hljs-built_in">len</span>(results)}</span> matches for '<span class="hljs-subst">{query}</span>' ---"</span>)
        <span class="hljs-keyword">for</span> filepath, text <span class="hljs-keyword">in</span> results:
            print(<span class="hljs-string">f"Match in: <span class="hljs-subst">{filepath}</span>"</span>)
            <span class="hljs-comment"># print(f"Snippet: {text[:200]}...") # Optional: print snippet</span>
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">f"\nNo matches found for '<span class="hljs-subst">{query}</span>'."</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># You need pytesseract and the Tesseract engine installed</span>
    <span class="hljs-comment"># process_screenshots()</span>
    <span class="hljs-comment"># search_screenshots("your search term here")</span>
    print(<span class="hljs-string">"Script ready. Install pytesseract/Tesseract, update config, then run process/search functions."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This script needs <strong><code>pytesseract</code></strong> and the underlying <strong>Tesseract OCR engine</strong> (must be installed separately on your OS). We use <strong><code>sqlite3</code></strong> to create a lightweight, local database. The <code>process_screenshots</code> function iterates over the image files, runs <code>pytesseract.image_to_string()</code>, and inserts the result into the DB. The <code>search_screenshots</code> function then allows you to query the indexed text. This is a life-saver for finding old error traces or configuration details hidden in images.</p>
<h2>7. Quick AST Import Tracker</h2>
<h3>Problem Solved</h3>
<p>When reviewing legacy code or cleaning up a massive Python file, you often wonder which imported modules are <em>actually</em> used by the logic. Commenting out imports until the code breaks is frustrating.</p>
<h3>Solution Overview</h3>
<p>The <strong><code>ast</code> (Abstract Syntax Tree)</strong> module allows Python to inspect its own structure. This script reads a Python file, parses its AST, and reports all imported modules (including <code>from X import Y</code>) but excludes any imports that are never referenced in the subsequent code body.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-74 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQzwI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-74">
<div class="animated-opacity ng-tns-c1877124198-74">
<pre class="ng-tns-c1877124198-74"><code class="code-container formatted ng-tns-c1877124198-74" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> ast
<span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">analyze_python_file</span>(<span class="hljs-params">filepath</span>):</span>
    <span class="hljs-string">"""Analyzes a Python file to track imported modules and their usage."""</span>
    <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(filepath, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        tree = ast.parse(f.read())

    imported_names = {} <span class="hljs-comment"># {alias: module_name or name}</span>
    used_names = <span class="hljs-built_in">set</span>()

    <span class="hljs-comment"># 1. Collect all imported names</span>
    <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> ast.walk(tree):
        <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(node, ast.Import):
            <span class="hljs-keyword">for</span> alias <span class="hljs-keyword">in</span> node.names:
                imported_names[alias.asname <span class="hljs-keyword">or</span> alias.name] = alias.name
        <span class="hljs-keyword">elif</span> <span class="hljs-built_in">isinstance</span>(node, ast.ImportFrom):
            <span class="hljs-keyword">if</span> node.module:
                <span class="hljs-keyword">for</span> alias <span class="hljs-keyword">in</span> node.names:
                    imported_names[alias.asname <span class="hljs-keyword">or</span> alias.name] = <span class="hljs-string">f"<span class="hljs-subst">{node.module}</span>.<span class="hljs-subst">{alias.name}</span>"</span>
            
    <span class="hljs-comment"># 2. Find all names used in the code</span>
    <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> ast.walk(tree):
        <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(node, ast.Name) <span class="hljs-keyword">and</span> <span class="hljs-built_in">isinstance</span>(node.ctx, (ast.Load, ast.Store, ast.Del)):
            used_names.add(node.<span class="hljs-built_in">id</span>)

    <span class="hljs-comment"># 3. Compare and Report</span>
    unused_imports = {}
    <span class="hljs-keyword">for</span> alias, module_name <span class="hljs-keyword">in</span> imported_names.items():
        <span class="hljs-comment"># Check if the alias (or the name itself) was ever used</span>
        <span class="hljs-keyword">if</span> alias <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> used_names:
            unused_imports[alias] = module_name
            
    print(<span class="hljs-string">f"--- Unused Imports in <span class="hljs-subst">{filepath}</span> ---"</span>)
    <span class="hljs-keyword">if</span> unused_imports:
        <span class="hljs-keyword">for</span> alias, module_name <span class="hljs-keyword">in</span> unused_imports.items():
            print(<span class="hljs-string">f"Potential unused import: <span class="hljs-subst">{module_name}</span> (as <span class="hljs-subst">{alias}</span>)"</span>)
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">"✅ Clean: No immediately obvious unused imports found."</span>)
        
    <span class="hljs-keyword">return</span> unused_imports

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># Example usage: Pass a Python file path</span>
    <span class="hljs-comment"># If you run this script on itself, it will find its own unused imports (if any)</span>
    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(sys.argv) &lt; <span class="hljs-number">2</span>:
        print(<span class="hljs-string">f"Usage: python <span class="hljs-subst">{sys.argv[<span class="hljs-number">0</span>]}</span> &lt;path/to/your/file.py&gt;"</span>)
    <span class="hljs-keyword">else</span>:
        filepath = sys.argv[<span class="hljs-number">1</span>]
        <span class="hljs-comment"># analyze_python_file(filepath)</span>
        print(<span class="hljs-string">"Script ready. Pass a Python file path as an argument and uncomment 'analyze_python_file' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This is a sophisticated static analysis tool. The <code>ast</code> module creates a tree representation of the code. We first walk the tree and populate <code>imported_names</code> with every alias and module. We then walk the tree again to find every <code>ast.Name</code> node that is being <code>Load</code>ed (i.e., used). By comparing the two sets (<code>imported_names</code> vs. <code>used_names</code>), we can identify modules that were imported but whose names never appeared in the code body. This is a powerful, dependency-free way to clean up large files and improve cold-start times.</p>
<h2>8. Git Commit Time Visualizer (Activity Heatmap)</h2>
<h3>Problem Solved</h3>
<p>Sometimes you need to analyze when you (or your team) are most productive, or figure out why commits stop abruptly. The standard <code>git log</code> is too verbose for this.</p>
<h3>Solution Overview</h3>
<p>This script uses the <code>subprocess</code> module to run <code>git log</code>, extracts the commit timestamps, and generates a simple, text-based heatmap showing commit activity broken down by hour of the day and day of the week.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-75 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQ0AI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-75">
<div class="animated-opacity ng-tns-c1877124198-75">
<pre class="ng-tns-c1877124198-75"><code class="code-container formatted ng-tns-c1877124198-75" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> subprocess
<span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_commit_heatmap</span>(<span class="hljs-params">repo_path=<span class="hljs-string">'.'</span></span>):</span>
    <span class="hljs-string">"""Generates a text-based heatmap of commit times."""</span>
    
    <span class="hljs-comment"># Run git log and format the output as raw timestamps</span>
    <span class="hljs-keyword">try</span>:
        command = [
            <span class="hljs-string">'git'</span>, <span class="hljs-string">'log'</span>, <span class="hljs-string">'--all'</span>, 
            <span class="hljs-string">'--pretty=format:%at'</span> <span class="hljs-comment"># %at is author timestamp (seconds since epoch)</span>
        ]
        result = subprocess.run(
            command, 
            cwd=repo_path, 
            capture_output=<span class="hljs-literal">True</span>, 
            text=<span class="hljs-literal">True</span>, 
            check=<span class="hljs-literal">True</span>
        )
        timestamps = result.stdout.strip().split(<span class="hljs-string">'\n'</span>)
    <span class="hljs-keyword">except</span> subprocess.CalledProcessError <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Error running git: <span class="hljs-subst">{e.stderr.strip()}</span>"</span>)
        <span class="hljs-keyword">return</span>
    <span class="hljs-keyword">except</span> FileNotFoundError:
        print(<span class="hljs-string">"Error: Git executable not found."</span>)
        <span class="hljs-keyword">return</span>

    <span class="hljs-comment"># Initialize heatmap: [Day of Week][Hour of Day]</span>
    heatmap = defaultdict(<span class="hljs-keyword">lambda</span>: defaultdict(<span class="hljs-built_in">int</span>))
    
    <span class="hljs-keyword">for</span> ts <span class="hljs-keyword">in</span> timestamps:
        <span class="hljs-keyword">try</span>:
            timestamp = <span class="hljs-built_in">int</span>(ts)
            dt_object = datetime.datetime.fromtimestamp(timestamp)
            day_of_week = dt_object.weekday() <span class="hljs-comment"># Monday is 0, Sunday is 6</span>
            hour_of_day = dt_object.hour
            heatmap[day_of_week][hour_of_day] += <span class="hljs-number">1</span>
        <span class="hljs-keyword">except</span> ValueError:
            <span class="hljs-keyword">continue</span>

    <span class="hljs-comment"># Visualization</span>
    DAYS = [<span class="hljs-string">'Mon'</span>, <span class="hljs-string">'Tue'</span>, <span class="hljs-string">'Wed'</span>, <span class="hljs-string">'Thu'</span>, <span class="hljs-string">'Fri'</span>, <span class="hljs-string">'Sat'</span>, <span class="hljs-string">'Sun'</span>]
    HOURS = [<span class="hljs-string">f"<span class="hljs-subst">{h:02d}</span>"</span> <span class="hljs-keyword">for</span> h <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">24</span>)]
    
    print(<span class="hljs-string">"\n--- Git Commit Activity Heatmap (Commits Per Hour/Day) ---"</span>)
    print(<span class="hljs-string">"       "</span> + <span class="hljs-string">" "</span>.join(HOURS))
    print(<span class="hljs-string">"     "</span> + <span class="hljs-string">"-"</span> * (<span class="hljs-number">3</span> * <span class="hljs-number">24</span>))
    
    <span class="hljs-keyword">for</span> d_index, day <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(DAYS):
        row = <span class="hljs-string">f"<span class="hljs-subst">{day}</span> | "</span>
        <span class="hljs-keyword">for</span> h_index <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">24</span>):
            count = heatmap[d_index][h_index]
            <span class="hljs-comment"># Use simple characters for visualization</span>
            <span class="hljs-keyword">if</span> count == <span class="hljs-number">0</span>:
                char = <span class="hljs-string">' .'</span> 
            <span class="hljs-keyword">elif</span> count &lt; <span class="hljs-number">5</span>:
                char = <span class="hljs-string">' ░'</span>
            <span class="hljs-keyword">elif</span> count &lt; <span class="hljs-number">15</span>:
                char = <span class="hljs-string">' ▒'</span>
            <span class="hljs-keyword">else</span>:
                char = <span class="hljs-string">' ▓'</span>
            row += char
        print(row)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># create_commit_heatmap('.') # Runs on the current directory if it's a Git repo</span>
    print(<span class="hljs-string">"Script ready. Uncomment 'create_commit_heatmap' in a Git repository to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>We use <code>subprocess</code> to execute <code>git log --pretty=format:%at</code>, which is the fastest way to get raw timestamps. The output is parsed into a <code>datetime</code> object. We then use a <code>defaultdict</code> to count commits by day (<code>weekday()</code> 0-6) and hour (<code>hour</code> 0-23). The final print loop iterates through the structure, using simple Unicode block characters (░, ▒, ▓) to create a visual heatmap. I love using this to quickly diagnose burnout or spot patterns in team collaboration.</p>
<h2>9. Daily Log Summarizer (Jupyter Notebook/Text Files)</h2>
<h3>Problem Solved</h3>
<p>Daily logs, meeting notes, or research journals grow quickly into thousands of lines. Finding the key takeaways or action items from last week's notes is a huge effort.</p>
<h3>Solution Overview</h3>
<p>This script uses the <strong><code>gensim</code></strong> library (specifically the TextRank algorithm) for <strong>unsupervised text summarization</strong>. It takes a collection of text files (or a single large log file) and generates a concise, fixed-length summary of the content.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-76 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQ0QI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-76">
<div class="animated-opacity ng-tns-c1877124198-76">
<pre class="ng-tns-c1877124198-76"><code class="code-container formatted ng-tns-c1877124198-76" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> gensim.summarization <span class="hljs-keyword">import</span> summarize <span class="hljs-comment"># pip install gensim</span>
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque

LOG_DIR = <span class="hljs-string">'./daily_logs'</span> <span class="hljs-comment"># &lt;-- CHANGE THIS</span>
SUMMARY_LENGTH = <span class="hljs-number">0.3</span> <span class="hljs-comment"># 30% of original text length</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">summarize_logs</span>():</span>
    all_text = []
    
    <span class="hljs-comment"># Load all text files in the log directory</span>
    <span class="hljs-keyword">for</span> root, _, files <span class="hljs-keyword">in</span> os.walk(LOG_DIR):
        <span class="hljs-keyword">for</span> file_name <span class="hljs-keyword">in</span> files:
            <span class="hljs-keyword">if</span> file_name.endswith((<span class="hljs-string">'.txt'</span>, <span class="hljs-string">'.log'</span>)):
                file_path = os.path.join(root, file_name)
                <span class="hljs-keyword">try</span>:
                    <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(file_path, <span class="hljs-string">'r'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> f:
                        all_text.append(f.read())
                <span class="hljs-keyword">except</span> Exception:
                    <span class="hljs-keyword">continue</span>
    
    <span class="hljs-comment"># Combine text for holistic summarization</span>
    combined_text = <span class="hljs-string">"\n\n"</span>.join(all_text)
    
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> combined_text.strip():
        print(<span class="hljs-string">"No content found in logs to summarize."</span>)
        <span class="hljs-keyword">return</span>

    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Use TextRank algorithm for summarization</span>
        summary = summarize(combined_text, ratio=SUMMARY_LENGTH) 
        
        print(<span class="hljs-string">"\n--- Daily Log Summary ---"</span>)
        print(summary)
        print(<span class="hljs-string">"-"</span> * <span class="hljs-number">30</span>)
        
        <span class="hljs-comment"># Optional: Save the summary</span>
        <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">'daily_summary.txt'</span>, <span class="hljs-string">'w'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> f:
            f.write(summary)
        print(<span class="hljs-string">"Summary saved to daily_summary.txt"</span>)

    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Summarization failed (check gensim/TextRank requirements): <span class="hljs-subst">{e}</span>"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># You need the 'gensim' library: pip install gensim</span>
    <span class="hljs-comment"># summarize_logs()</span>
    print(<span class="hljs-string">"Script ready. Install gensim, update LOG_DIR, and uncomment 'summarize_logs' to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This relies on <strong><code>gensim</code></strong>'s summarization module. The <code>summarize</code> function implements the TextRank algorithm, which identifies the most important sentences based on graph theory (sentences that share many common words are ranked higher). By setting <code>ratio=0.3</code>, we ask the script to return a summary that is 30% of the original text's length. I use this every Friday to quickly review my week's work notes and compile my status report.</p>
<h2>10. PDF Splitter/Merger with Auto-Index</h2>
<h3>Problem Solved</h3>
<p>Splitting a 500-page bank statement or a large technical manual into individual chapters is a manual drag. Merging several small reports into one indexed PDF is also a chore.</p>
<h3>Solution Overview</h3>
<p>The <strong><code>PyPDF2</code></strong> library (or the newer <code>pypdf</code>) is a workhorse for PDF manipulation. This script provides functions to split a PDF based on page ranges and merge multiple PDFs into one, automatically adding a Table of Contents (TOC) using bookmarks if required.</p>
<h3>The Code</h3>
<div class="code-block ng-tns-c1877124198-77 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQ0gI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-77">
<div class="animated-opacity ng-tns-c1877124198-77">
<pre class="ng-tns-c1877124198-77"><code class="code-container formatted ng-tns-c1877124198-77" role="text" data-test-id="code-content"><span class="hljs-keyword">from</span> PyPDF2 <span class="hljs-keyword">import</span> PdfReader, PdfWriter <span class="hljs-comment"># pip install PyPDF2</span>
<span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pdf_split</span>(<span class="hljs-params">input_path, output_dir, page_ranges</span>):</span>
    <span class="hljs-string">"""Splits a PDF based on a dictionary of {title: [start_page, end_page]}."""</span>
    reader = PdfReader(input_path)
    os.makedirs(output_dir, exist_ok=<span class="hljs-literal">True</span>)

    <span class="hljs-keyword">for</span> title, (start, end) <span class="hljs-keyword">in</span> page_ranges.items():
        writer = PdfWriter()
        <span class="hljs-comment"># Pages are 0-indexed, so we use start-1 to end</span>
        <span class="hljs-keyword">for</span> page_num <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(start - <span class="hljs-number">1</span>, end): 
            writer.add_page(reader.pages[page_num])

        output_path = os.path.join(output_dir, <span class="hljs-string">f"<span class="hljs-subst">{title}</span>.pdf"</span>)
        <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(output_path, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> output_file:
            writer.write(output_file)
        print(<span class="hljs-string">f"Created: <span class="hljs-subst">{output_path}</span>"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pdf_merge</span>(<span class="hljs-params">file_list, output_path</span>):</span>
    <span class="hljs-string">"""Merges a list of PDFs and adds bookmarks for indexing."""</span>
    merger = PdfWriter()

    <span class="hljs-keyword">for</span> path <span class="hljs-keyword">in</span> file_list:
        title = os.path.basename(path).replace(<span class="hljs-string">".pdf"</span>, <span class="hljs-string">""</span>)
        <span class="hljs-comment"># Get the page number where this file starts</span>
        page_start = <span class="hljs-built_in">len</span>(merger.pages) 
        merger.append(path)
        <span class="hljs-comment"># Add a bookmark pointing to the start of the merged file</span>
        merger.add_outline_item(title, page_start) 

    <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(output_path, <span class="hljs-string">"wb"</span>) <span class="hljs-keyword">as</span> output_file:
        merger.write(output_file)
    print(<span class="hljs-string">f"Merged and indexed PDF created: <span class="hljs-subst">{output_path}</span>"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># You need PyPDF2: pip install PyPDF2</span>
    
    <span class="hljs-comment"># --- SPLIT EXAMPLE ---</span>
    <span class="hljs-comment"># INPUT_PDF = 'large_manual.pdf' # &lt;-- CHANGE THIS</span>
    <span class="hljs-comment"># RANGES = {</span>
    <span class="hljs-comment">#     "Chapter 1 - Intro": [1, 10], </span>
    <span class="hljs-comment">#     "Chapter 2 - Setup": [11, 25]</span>
    <span class="hljs-comment"># }</span>
    <span class="hljs-comment"># pdf_split(INPUT_PDF, './split_output', RANGES)</span>
    
    <span class="hljs-comment"># --- MERGE EXAMPLE ---</span>
    <span class="hljs-comment"># MERGE_LIST = ['./report_a.pdf', './report_b.pdf', './report_c.pdf'] # &lt;-- CHANGE THIS</span>
    <span class="hljs-comment"># pdf_merge(MERGE_LIST, 'final_combined_report.pdf')</span>
    print(<span class="hljs-string">"Script ready. Install PyPDF2, update file paths, and uncomment the desired function to run."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>The <code>PdfReader</code> and <code>PdfWriter</code> objects from <code>PyPDF2</code> do the heavy lifting. In <code>pdf_split</code>, we loop through the page indices and add them to a new <code>PdfWriter</code>. In <code>pdf_merge</code>, we use <code>merger.append(path)</code> to add content, and the key trick is using <code>merger.add_outline_item(title, page_start)</code> which creates a bookmark (TOC entry) in the resulting PDF at the page number where the new file began. This is invaluable for finance, legal, or documentation teams.</p>
<h2>11. System Resource Dashboard (Cross-Platform)</h2>
<h3>Problem Solved</h3>
<p>Checking CPU load, memory usage, disk activity, or network bandwidth often requires opening three different system monitors, which distracts you from your main work.</p>
<h3>Solution Overview</h3>
<p>The <strong><code>psutil</code></strong> library provides an excellent cross-platform way to access system metrics. This script runs a simple, real-time dashboard in the terminal, giving you key metrics at a glance.</p>
<h3>The Code</h3>
<!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c1877124198-78 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQ0wI"><!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-78">
<div class="animated-opacity ng-tns-c1877124198-78">
<pre class="ng-tns-c1877124198-78"><code class="code-container formatted ng-tns-c1877124198-78" role="text" data-test-id="code-content"><span class="hljs-keyword">import</span> psutil <span class="hljs-comment"># pip install psutil</span>
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> sys

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">clear_screen</span>():</span>
    <span class="hljs-string">"""Clears the terminal screen."""</span>
    os.system(<span class="hljs-string">'cls'</span> <span class="hljs-keyword">if</span> os.name == <span class="hljs-string">'nt'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'clear'</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_sys_metrics</span>():</span>
    <span class="hljs-string">"""Fetches core system metrics using psutil."""</span>
    cpu_percent = psutil.cpu_percent(interval=<span class="hljs-literal">None</span>) <span class="hljs-comment"># Non-blocking call</span>
    mem_info = psutil.virtual_memory()
    disk_usage = psutil.disk_usage(<span class="hljs-string">'/'</span>) <span class="hljs-comment"># Use '/' for Linux/macOS, or 'C:' for Windows</span>
    net_io = psutil.net_io_counters()

    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">'CPU'</span>: <span class="hljs-string">f"<span class="hljs-subst">{cpu_percent:<span class="hljs-number">0.1</span>f}</span>%"</span>,
        <span class="hljs-string">'Memory'</span>: <span class="hljs-string">f"<span class="hljs-subst">{mem_info.percent:<span class="hljs-number">0.1</span>f}</span>% (<span class="hljs-subst">{mem_info.used / (<span class="hljs-number">1024</span>**<span class="hljs-number">3</span>):<span class="hljs-number">.2</span>f}</span> GB used)"</span>,
        <span class="hljs-string">'Disk'</span>: <span class="hljs-string">f"<span class="hljs-subst">{disk_usage.percent}</span>% (<span class="hljs-subst">{disk_usage.free / (<span class="hljs-number">1024</span>**<span class="hljs-number">3</span>):<span class="hljs-number">.2</span>f}</span> GB free)"</span>,
        <span class="hljs-string">'Net_Sent'</span>: <span class="hljs-string">f"<span class="hljs-subst">{net_io.bytes_sent / (<span class="hljs-number">1024</span>**<span class="hljs-number">2</span>):<span class="hljs-number">.2</span>f}</span> MB"</span>,
        <span class="hljs-string">'Net_Recv'</span>: <span class="hljs-string">f"<span class="hljs-subst">{net_io.bytes_recv / (<span class="hljs-number">1024</span>**<span class="hljs-number">2</span>):<span class="hljs-number">.2</span>f}</span> MB"</span>,
    }

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run_dashboard</span>(<span class="hljs-params">interval=<span class="hljs-number">1.0</span></span>):</span>
    clear_screen()
    print(<span class="hljs-string">"System Resource Dashboard (Press Ctrl+C to stop)"</span>)
    print(<span class="hljs-string">"-"</span> * <span class="hljs-number">40</span>)
    
    <span class="hljs-comment"># Get initial metrics to calculate CPU usage over an interval</span>
    psutil.cpu_percent(interval=<span class="hljs-literal">None</span>) 

    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
            metrics = get_sys_metrics()
            
            <span class="hljs-comment"># Print the dashboard</span>
            sys.stdout.write(<span class="hljs-string">'\033[F'</span>) <span class="hljs-comment"># Move cursor up (only works in some terminals)</span>
            sys.stdout.write(<span class="hljs-string">'\033[K'</span>) <span class="hljs-comment"># Clear line</span>
            
            print(<span class="hljs-string">f"Time: <span class="hljs-subst">{time.strftime('%H:%M:%S')}</span>"</span>)
            print(<span class="hljs-string">f"CPU Usage: <span class="hljs-subst">{metrics['CPU']}</span>"</span>)
            print(<span class="hljs-string">f"Memory:    <span class="hljs-subst">{metrics['Memory']}</span>"</span>)
            print(<span class="hljs-string">f"Disk Root: <span class="hljs-subst">{metrics['Disk']}</span>"</span>)
            print(<span class="hljs-string">f"Net Sent:  <span class="hljs-subst">{metrics['Net_Sent']}</span>"</span>)
            print(<span class="hljs-string">f"Net Recv:  <span class="hljs-subst">{metrics['Net_Recv']}</span>"</span>)
            
            time.sleep(interval)
            
    <span class="hljs-keyword">except</span> KeyboardInterrupt:
        print(<span class="hljs-string">"\nDashboard stopped."</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># You need psutil: pip install psutil</span>
    <span class="hljs-comment"># run_dashboard(interval=2)</span>
    print(<span class="hljs-string">"Script ready. Install psutil and uncomment 'run_dashboard' to run the real-time terminal monitor."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p><strong><code>psutil</code></strong> abstracts away the OS-specific commands. The key is calling <code>psutil.cpu_percent(interval=None)</code> once before the loop to prime it, and then inside the loop, calling it again. It uses the difference between the two calls to get an accurate CPU usage percentage for that interval. The <code>sys.stdout.write('\033[F')</code> command is a neat trick to refresh the output in place in the terminal, creating a true real-time dashboard effect. I keep this running on my secondary monitor during build processes or stress tests.</p>
<h2>12. Local Web API to Trigger Small Automations</h2>
<h3>Problem Solved</h3>
<p>You want to run a simple Python script (like "Clean Temp Files" or "Trigger Backup") from any device on your local network (e.g., your phone or a separate machine), or trigger it easily via a desktop shortcut.</p>
<h3>Solution Overview</h3>
<p>We can use a super lightweight web framework like <strong><code>Flask</code></strong> to expose our simple automation functions as a local API endpoint. When you visit <code>http://localhost:5000/trigger_cleanup</code>, the Python function runs.</p>
<h3>The Code</h3>
<!----><!----><!----><!----><!----><!---->
<div class="code-block ng-tns-c1877124198-79 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwicu_ve-O6QAxUAAAAAHQAAAAAQ1AI">
<div class="code-block-decoration header-formatted gds-title-s ng-tns-c1877124198-79 ng-star-inserted"><span class="ng-tns-c1877124198-79">Python</span>
<div class="buttons ng-tns-c1877124198-79 ng-star-inserted"><!----><!----></div>
<!----></div>
<!---->
<div class="formatted-code-block-internal-container ng-tns-c1877124198-79">
<div class="animated-opacity ng-tns-c1877124198-79">
<pre class="ng-tns-c1877124198-79"><code class="code-container formatted ng-tns-c1877124198-79" role="text" data-test-id="code-content"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify <span class="hljs-comment"># pip install flask</span>
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> time

app = Flask(__name__)

<span class="hljs-comment"># --- Simple Automation Function ---</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cleanup_temp_files</span>():</span>
    <span class="hljs-string">"""A placeholder for your actual cleanup automation."""</span>
    
    <span class="hljs-comment"># Example: Delete files in a temp folder older than 1 day</span>
    TEMP_DIR = <span class="hljs-string">'./temp_storage'</span> 
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(TEMP_DIR):
        os.makedirs(TEMP_DIR)
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        
    deleted_count = <span class="hljs-number">0</span>
    now = time.time()
    <span class="hljs-keyword">for</span> filename <span class="hljs-keyword">in</span> os.listdir(TEMP_DIR):
        filepath = os.path.join(TEMP_DIR, filename)
        <span class="hljs-keyword">if</span> os.path.isfile(filepath) <span class="hljs-keyword">and</span> now - os.stat(filepath).st_mtime &gt; (<span class="hljs-number">24</span> * <span class="hljs-number">3600</span>):
            os.remove(filepath)
            deleted_count += <span class="hljs-number">1</span>
            
    <span class="hljs-keyword">return</span> deleted_count

<span class="hljs-comment"># --- API Endpoint ---</span>
<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/trigger_cleanup'</span>, methods=[<span class="hljs-string">'POST'</span>, <span class="hljs-string">'GET'</span>]</span>)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">trigger_cleanup</span>():</span>
    deleted = cleanup_temp_files()
    <span class="hljs-keyword">if</span> deleted &gt; <span class="hljs-number">0</span>:
        message = <span class="hljs-string">f"Cleanup successful. Deleted <span class="hljs-subst">{deleted}</span> old temporary files."</span>
    <span class="hljs-keyword">else</span>:
        message = <span class="hljs-string">"Cleanup ran. No old files found or temp directory was empty."</span>
        
    <span class="hljs-comment"># Return a JSON response</span>
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"status"</span>: <span class="hljs-string">"success"</span>, <span class="hljs-string">"message"</span>: message, <span class="hljs-string">"files_deleted"</span>: deleted})

<span class="hljs-meta">@app.route(<span class="hljs-params"><span class="hljs-string">'/'</span>, methods=[<span class="hljs-string">'GET'</span>]</span>)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Automation Hub Running. Visit /trigger_cleanup to run the task."</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># Run the server on the local network IP (0.0.0.0) so other devices can access it.</span>
    <span class="hljs-comment"># Set host='127.0.0.1' if you only want local access.</span>
    <span class="hljs-comment"># You need Flask: pip install Flask</span>
    <span class="hljs-comment"># app.run(host='0.0.0.0', port=5000, debug=False) </span>
    print(<span class="hljs-string">"Script ready. Install Flask, uncomment 'app.run', and access http://127.0.0.1:5000 in your browser."</span>)
</code></pre>
<!----></div>
</div>
</div>
<!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!---->
<h3>Code Explanation &amp; Use Cases</h3>
<p>This script requires <strong><code>Flask</code></strong>. We define a function <code>cleanup_temp_files</code> (where you'd put any short automation logic). We then use the <code>@app.route</code> decorator to link this function to a web URL <code>/trigger_cleanup</code>. When someone hits this URL, the function executes, and the server returns a clear JSON response. This is my favorite "lazy button" for tasks. I have this running on a headless Raspberry Pi, and I simply hit the URL from my phone to run a full backup.</p>
<h2>Final Thoughts: The Power of Intentional Automation</h2>
<p>These scripts are more than just Python code; they are little pockets of focused time-saving. By moving beyond the basics and tackling advanced, real-world annoyances like IMAP IDLE and AST parsing, you truly harness the power Python offers to us as developers.</p>
<p>The best automation isn't one you run once&mdash;it's the one you forget about because it's running silently in the background, making your workday smoother.</p>
<p>Now, take one of these, customize the configuration paths, and set it up on a scheduler (Cron, Task Scheduler, or even our Flask API). I guarantee you'll feel that satisfying click as you eliminate a repetitive task forever. Happy scripting!</p>
</div>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/BZ7Q2cEvNy1Mk5YEQ7y2wRyPq5Vero5Zasq7bOMM.png" type="image/png" length="1455105" />
        <media:content url="https://manamil.dev/storage/uploads/posts/BZ7Q2cEvNy1Mk5YEQ7y2wRyPq5Vero5Zasq7bOMM.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Thu, 13 Nov 2025 10:47:26 +0000</pubDate>

      
                        <category><![CDATA[Python automation]]></category>
                  <category><![CDATA[Python scripts]]></category>
                  <category><![CDATA[automate daily tasks]]></category>
                  <category><![CDATA[productivity]]></category>
                  <category><![CDATA[time saving]]></category>
                  <category><![CDATA[Python programming]]></category>
                  <category><![CDATA[file management]]></category>
                  <category><![CDATA[email automation]]></category>
                  <category><![CDATA[data entry]]></category>
                  <category><![CDATA[task automation]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Laravel 12 – Fixing storage:link Asset Error]]></title>
      <link>https://manamil.dev/blog/laravel/laravel-12-fixing-storage-link-asset-error</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel-12-fixing-storage-link-asset-error</guid>

      
      <description><![CDATA[
        <p>Learn how to resolve the common php artisan storage:link asset issue in Laravel 12, including missing symlink problems, shared‑hosting restrictions, filesystem disk settings, and best practices to ensure uploaded files are publicly accessible.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/D7XxPVdELeEyWsKHSV9BE95CtymLhWnYqwJ7iaDr.png" alt="Laravel 12 – Fixing storage:link Asset Error" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 data-start="320" data-end="343"><strong data-start="327" data-end="343">Introduction</strong></h2>
<p data-start="344" data-end="456">Laravel 12 has made file and storage handling even smoother &mdash; but many developers still face the common error:</p>
<p data-start="344" data-end="456"><strong>&ldquo;The asset cannot be found&rdquo; or &ldquo;storage:link not working.&rdquo;</strong></p>
<p data-start="519" data-end="738">This usually happens when your <strong data-start="550" data-end="575">storage symbolic link</strong> isn&rsquo;t properly connected to the <code data-start="608" data-end="624">public/storage</code> directory.<br data-start="635" data-end="638">In this guide, we&rsquo;ll fix this error step-by-step so your images, uploads, and assets load perfectly.</p>
<h2 data-start="745" data-end="782"><strong data-start="752" data-end="782">1. Understanding the Error</strong></h2>
<p data-start="784" data-end="869">When you upload files (like user images or documents) in Laravel, they are stored in:</p>
<p data-start="784" data-end="869">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="784" data-end="869">storage/app/public</p>
<p data-start="784" data-end="869">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="784" data-end="869">But for browsers to access them publicly, Laravel creates a symbolic link:</p>
<p data-start="784" data-end="869">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="784" data-end="869">public/storage &rarr; storage/app/public</p>
<p data-start="784" data-end="869">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="784" data-end="869">If this link is missing or broken, your images won&rsquo;t show &mdash; and you&rsquo;ll get the <strong data-start="1097" data-end="1120">storage asset error</strong>.</p>
<h2 data-start="1128" data-end="1170"><strong data-start="1135" data-end="1170">2. Run the Storage Link Command</strong></h2>
<p data-start="1172" data-end="1220">Run this artisan command from your project root:</p>
<p data-start="1172" data-end="1220">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1172" data-end="1220">php artisan storage:link</p>
<p data-start="1172" data-end="1220">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1172" data-end="1220">This will create a link between:</p>
<p data-start="1172" data-end="1220">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1172" data-end="1220">public/storage &rarr; storage/app/public</p>
<p data-start="1172" data-end="1220">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1172" data-end="1220">Now your files should be accessible via:</p>
<p data-start="1172" data-end="1220">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1172" data-end="1220">{{ asset('storage/filename.jpg') }}</p>
<p data-start="1172" data-end="1220">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="1430" data-end="1484"><strong data-start="1437" data-end="1484">3. If You Get &ldquo;Target Already Exists&rdquo; Error</strong></h2>
<p data-start="1486" data-end="1510">Sometimes you might see:</p>
<p data-start="1486" data-end="1510">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1486" data-end="1510">Error: The "public/storage" directory already exists.</p>
<p data-start="1486" data-end="1510">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1486" data-end="1510">To fix it:</p>
<p data-start="1486" data-end="1510">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1486" data-end="1510">rm -rf public/storage<br>php artisan storage:link</p>
<p data-start="1486" data-end="1510">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1486" data-end="1510">This removes the old broken link and creates a fresh one.</p>
<h2 data-start="1709" data-end="1745"><strong data-start="1716" data-end="1745">4. Check File Permissions</strong></h2>
<p data-start="1747" data-end="1806">Make sure the storage directories have correct permissions:</p>
<p data-start="1747" data-end="1806">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1747" data-end="1806">chmod -R 775 storage<br>chmod -R 775 bootstrap/cache</p>
<p data-start="1747" data-end="1806">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1870" data-end="1927">If you&rsquo;re on Linux or Ubuntu, you can also set ownership:</p>
<p data-start="1747" data-end="1806">&lt;pre&gt;&lt;code&gt;sudo chown -R www-data:www-data storage<br>sudo chown -R www-data:www-data bootstrap/cache&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1747" data-end="1806">This ensures Laravel can write and read files properly.</p>
<h2 data-start="2091" data-end="2142"><strong data-start="2098" data-end="2142">5. Use Correct Asset Path in Blade Files</strong></h2>
<p data-start="2144" data-end="2184">Use this format in your Blade templates:</p>
<p data-start="2144" data-end="2184">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2144" data-end="2184">&amp;lt;img src="{{ asset('storage/file name.jpg') }}" alt="Profile Picture" /&amp;gt;</p>
<p data-start="2144" data-end="2184">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2144" data-end="2184">❌ Don&rsquo;t use <code data-start="2280" data-end="2302">/storage/app/public/</code> &mdash; that&rsquo;s a private directory.<br data-start="2332" data-end="2335">✅ Always use <code data-start="2348" data-end="2370">asset('storage/...')</code> or <code data-start="2374" data-end="2394">url('storage/...')</code>.</p>
<h2 data-start="2402" data-end="2449"><strong data-start="2409" data-end="2449">6. Double Check <code data-start="2427" data-end="2433">.env</code> Configuration</strong></h2>
<p data-start="2451" data-end="2487">Make sure your <code data-start="2466" data-end="2472">.env</code> file includes:</p>
<p data-start="2451" data-end="2487">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2451" data-end="2487">FILESYSTEM_DISK=public</p>
<p data-start="2451" data-end="2487">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2451" data-end="2487">And your <code data-start="2529" data-end="2553">config/filesystems.php</code> has:</p>
<p data-start="2451" data-end="2487">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2451" data-end="2487">'public' =&gt; [<br>&nbsp; &nbsp; 'driver' =&gt; 'local',<br>&nbsp; &nbsp; 'root' =&gt; storage_path('app/public'),<br>&nbsp; &nbsp; 'url' =&gt; env('APP_URL').'/storage',<br>&nbsp; &nbsp; 'visibility' =&gt; 'public',<br>],</p>
<p data-start="2451" data-end="2487">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2451" data-end="2487">If you made any changes, clear the config cache:</p>
<p data-start="2451" data-end="2487">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2451" data-end="2487">php artisan config:clear</p>
<p data-start="2451" data-end="2487">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="2817" data-end="2877"><strong data-start="2824" data-end="2877">7. Bonus Tip &ndash; Deploying on Shared Hosting or VPS</strong></h2>
<p data-start="2879" data-end="3020">If you&rsquo;re on a shared hosting (like cPanel) and <code data-start="2927" data-end="2953">php artisan storage:link</code> doesn&rsquo;t work,<br data-start="2967" data-end="2970">you can manually create a symbolic link using SSH:</p>
<p data-start="2879" data-end="3020">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2879" data-end="3020">ln -s /home/username/project/storage/app/public /home/username/public_html/storage</p>
<p data-start="2879" data-end="3020">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2879" data-end="3020">Or use <strong data-start="3124" data-end="3152">Laravel&rsquo;s custom command</strong> inside a deployment script to recreate the link automatically.</p>
<h2 data-start="3222" data-end="3242"><strong data-start="3228" data-end="3242">Conclusion</strong></h2>
<p data-start="3244" data-end="3409">That&rsquo;s it! You&rsquo;ve successfully fixed the <strong data-start="3285" data-end="3324">Laravel 12 storage:link asset error</strong>.<br data-start="3325" data-end="3328">Now your uploaded images and files will display correctly without broken links.</p>
<p data-start="3411" data-end="3477">If you&rsquo;re setting up Laravel on a new server, make sure to always:</p>
<ol>
<li data-start="3480" data-end="3510">Run <code data-start="3484" data-end="3510">php artisan storage:link</code></li>
<li data-start="3513" data-end="3542">Set proper folder permissions</li>
<li>Verify <code data-start="3552" data-end="3561">APP_URL</code> and <code data-start="3566" data-end="3583">FILESYSTEM_DISK</code> in <code data-start="3587" data-end="3593">.env</code></li>
</ol>
<h2 data-start="271" data-end="315"><strong data-start="276" data-end="313">Frequently Asked Questions (FAQs)</strong></h2>
<h2 data-start="317" data-end="381"><strong data-start="321" data-end="379">1. What does <code data-start="336" data-end="362">php artisan storage:link</code> do in Laravel?</strong></h2>
<p data-start="382" data-end="593">The <code data-start="386" data-end="412">php artisan storage:link</code> command creates a symbolic link between <code data-start="453" data-end="469">public/storage</code> and <code data-start="474" data-end="494">storage/app/public</code>.<br data-start="495" data-end="498">This allows files stored in Laravel&rsquo;s storage folder to be publicly accessible via the browser.</p>
<h2 data-start="600" data-end="664"><strong data-start="604" data-end="662">2. Why is my Laravel storage:link command not working?</strong></h2>
<p data-start="665" data-end="828">This usually happens when the <code data-start="695" data-end="711">public/storage</code> folder already exists, or when you don&rsquo;t have the correct permissions.<br data-start="782" data-end="785">Delete the existing link and recreate it:</p>
<p data-start="665" data-end="828">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="665" data-end="828">rm -rf public/storage<br>php artisan storage:link</p>
<p data-start="665" data-end="828">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="894" data-end="977"><strong data-start="898" data-end="975">3. How can I fix the &ldquo;The public/storage directory already exists&rdquo; error?</strong></h2>
<p data-start="978" data-end="1043">Simply remove the existing directory and run the command again:</p>
<p data-start="978" data-end="1043">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="978" data-end="1043">rm -rf public/storage<br>php artisan storage:link</p>
<p data-start="978" data-end="1043">&lt;/code&gt;&lt;/pre&gt;</p>
<p>This will create a fresh symbolic link.</p>
<h2 data-start="1149" data-end="1236"><strong data-start="1153" data-end="1234">4. My uploaded images are not showing even after running&nbsp;<code data-start="1212" data-end="1226">storage:link</code>. Why?</strong></h2>
<p data-start="1237" data-end="1258">Check these points:</p>
<ul data-start="1259" data-end="1506">
<li data-start="1259" data-end="1298">
<p data-start="1261" data-end="1298">File exists in <code data-start="1276" data-end="1296">storage/app/public</code></p>
</li>
<li data-start="1299" data-end="1407">
<p data-start="1301" data-end="1338">You used the correct path in Blade:</p>
</li>
</ul>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>&amp;lt;img src="{{ asset('storage/file name.jpg') }}" /&amp;gt;</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<ul>
<li data-start="1408" data-end="1463">
<p data-start="1410" data-end="1463">Proper permissions are set (<code data-start="1438" data-end="1460">chmod -R 775 storage</code>)</p>
</li>
<li data-start="1464" data-end="1506">
<p data-start="1466" data-end="1506"><code data-start="1466" data-end="1472">.env</code> includes <code data-start="1482" data-end="1506">FILESYSTEM_DISK=public</code></p>
</li>
</ul>
<h2 data-start="1513" data-end="1588"><strong data-start="1517" data-end="1586">5. How to fix storage link error on shared hosting (like cPanel)?</strong></h2>
<p data-start="1589" data-end="1686">On shared hosting, artisan commands may be restricted.<br data-start="1643" data-end="1646">Use SSH and run this command manually:</p>
<p data-start="1589" data-end="1686">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1589" data-end="1686">ln -s /home/username/project/storage/app/public /home/username/public_html/storage</p>
<p data-start="1589" data-end="1686">&lt;/pre&gt;&lt;/code&gt;</p>
<p data-start="1589" data-end="1686">Or ask your hosting provider to create the symbolic link for you.</p>
<h2 data-start="1854" data-end="1930"><strong data-start="1858" data-end="1928">6. What should be the correct <code data-start="1890" data-end="1907">FILESYSTEM_DISK</code> setting in <code data-start="1919" data-end="1925">.env</code>?</strong></h2>
<p data-start="1931" data-end="1937">Use:</p>
<p data-start="1931" data-end="1937">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1931" data-end="1937">FILESYSTEM_DISK=public&nbsp;</p>
<p data-start="1931" data-end="1937">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1969" data-end="2096">This ensures that files uploaded using Laravel&rsquo;s <code data-start="2018" data-end="2027">Storage</code> facade are stored in the <code data-start="2053" data-end="2061">public</code> disk and can be accessed publicly.</p>
<h2 data-start="2103" data-end="2171"><strong data-start="2107" data-end="2169">7. Do I need to run <code data-start="2129" data-end="2143">storage:link</code> after every deployment?</strong></h2>
<p data-start="2172" data-end="2371">Yes, ideally you should.<br data-start="2196" data-end="2199">When deploying Laravel to a new server or after clearing files, the symbolic link may not exist &mdash; running <code data-start="2305" data-end="2331">php artisan storage:link</code> ensures all file assets work correctly.</p>
<h2 data-start="2378" data-end="2440"><strong data-start="2382" data-end="2438">8. Can I use a custom path for Laravel storage link?</strong></h2>
<p data-start="2441" data-end="2491">Yes. You can create custom symbolic links using:</p>
<p data-start="2441" data-end="2491">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2441" data-end="2491">php artisan storage:link --relative</p>
<p data-start="2441" data-end="2491">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2441" data-end="2491">or manually specify paths via <code data-start="2570" data-end="2594">config/filesystems.php</code>.<br data-start="2595" data-end="2598">However, using the default public link is recommended for simplicity and compatibility.</p>
<h2><strong>9. Why do I need storage:link in Laravel?</strong></h2>
<p class="ds-markdown-paragraph">The storage:link command creates a secure way to serve user-uploaded files while keeping them outside the public directory for security reasons.</p>
<h2><strong>10. Can I use storage:link on shared hosting?</strong></h2>
<p class="ds-markdown-paragraph">&nbsp;It depends on your hosting provider. Some allow symbolic links, while others don't. Contact your provider or use alternative methods like serving files through controllers.</p>
<h2><strong>11. What's the difference between public disk and storage:link?</strong></h2>
<p class="ds-markdown-paragraph">The public disk is a filesystem configuration, while storage:link creates a symbolic link to make files in storage/app/public accessible via the web.</p>
<h2><strong>12. How can I check if my storage link is working?</strong></h2>
<p class="ds-markdown-paragraph">Create a test file in storage/app/public and try to access it via your browser using the /storage/ URL.</p>
<h2><strong>13. What should I do if storage:link fails on production?</strong></h2>
<ol start="1">
<li>
<p class="ds-markdown-paragraph">Check file permissions</p>
</li>
<li>
<p class="ds-markdown-paragraph">Verify directory existence</p>
</li>
<li>
<p class="ds-markdown-paragraph">Check server symbolic link support</p>
</li>
<li>
<p class="ds-markdown-paragraph">Use manual symbolic link creation</p>
</li>
<li>
<p class="ds-markdown-paragraph">Contact your hosting provider</p>
</li>
</ol>
<h2><strong>14. Can I have multiple storage links?</strong></h2>
<p class="ds-markdown-paragraph">&nbsp;Yes, you can define multiple links in your config/filesystems.php file.</p>
<h2><strong>15. Is it safe to delete the storage link?</strong></h2>
<p class="ds-markdown-paragraph">&nbsp;Yes, but your user-uploaded files won't be accessible via the web until you recreate the link.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/D7XxPVdELeEyWsKHSV9BE95CtymLhWnYqwJ7iaDr.png" type="image/png" length="1079443" />
        <media:content url="https://manamil.dev/storage/uploads/posts/D7XxPVdELeEyWsKHSV9BE95CtymLhWnYqwJ7iaDr.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 10 Nov 2025 08:42:59 +0000</pubDate>

      
                        <category><![CDATA[Laravel 12 storage link error]]></category>
                  <category><![CDATA[php artisan storage:link not working Laravel]]></category>
                  <category><![CDATA[Laravel storage asset issue]]></category>
                  <category><![CDATA[Laravel public storage symlink]]></category>
                  <category><![CDATA[Laravel shared hosting storage link fix]]></category>
                  <category><![CDATA[Laravel 12 filesystem public disk]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Laravel 12 Routing – Defining Routes in bootstrap/app.php]]></title>
      <link>https://manamil.dev/blog/laravel/laravel-12-routing-defining-routes-bootstrap-app</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel-12-routing-defining-routes-bootstrap-app</guid>

      
      <description><![CDATA[
        <p>Explore how to define and customize routes in Laravel 12 via bootstrap/app.php. Learn about web, API and console routes registration, route grouping, custom route files and best practices for maintainable routing.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/QEGjywhBu2xoBhwTe4bJGLso68fIx13OJ917MGWQ.png" alt="Laravel 12 Routing – Defining Routes in bootstrap/app.php" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 data-start="437" data-end="462"><strong data-start="444" data-end="460">Introduction</strong></h2>
<p data-start="463" data-end="779">Laravel 12 has simplified how applications are bootstrapped and routes are registered.<br data-start="549" data-end="552">Instead of the traditional <code data-start="579" data-end="595">routes/web.php</code> and <code data-start="600" data-end="616">routes/api.php</code> being loaded automatically through <code data-start="652" data-end="674">RouteServiceProvider</code>, Laravel 12 gives developers more control by defining routes directly in the <code data-start="752" data-end="771">bootstrap/app.php</code> file.</p>
<p data-start="781" data-end="933">This new approach makes the app startup process faster, cleaner, and easier to customize &mdash; especially for microservices or lightweight Laravel setups.</p>
<h3 data-start="940" data-end="981"><strong data-start="947" data-end="979">1. Old vs New Routing System</strong></h3>
<p data-start="983" data-end="1075">Before Laravel 12, your routes were usually registered through the <code data-start="1050" data-end="1072">RouteServiceProvider</code>:</p>
<p data-start="983" data-end="1075">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="983" data-end="1075">// In routes/web.php<br>Route::get('/', function () {<br>&nbsp; &nbsp; return view('welcome');<br>});</p>
<p data-start="983" data-end="1075">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="983" data-end="1075">Laravel automatically loaded these files via the provider.<br data-start="1229" data-end="1232">But from <strong data-start="1241" data-end="1262">Laravel 12 onward</strong>, you can define routes directly inside <code data-start="1302" data-end="1321">bootstrap/app.php</code> using the new closure-based bootstrapping style.</p>
<h3 data-start="1377" data-end="1430"><strong data-start="1384" data-end="1428">2. The New <code data-start="1397" data-end="1416">bootstrap/app.php</code> Structure</strong></h3>
<p data-start="1432" data-end="1499">A typical <code data-start="1442" data-end="1461">bootstrap/app.php</code> file in Laravel 12 looks like this:</p>
<p data-start="1432" data-end="1499">&lt;pre&gt;&lt;code&gt;</p>
<p>use Illuminate\Foundation\Application;<br>use Illuminate\Foundation\Configuration\Exceptions;<br>use Illuminate\Foundation\Configuration\Middleware;<br>use Illuminate\Support\Facades\Route;</p>
<p>return Application::configure(basePath: dirname(__DIR__))<br>&nbsp; &nbsp; -&gt;withRouting(<br>&nbsp; &nbsp; &nbsp; &nbsp; web: __DIR__.'/../routes/web.php',<br>&nbsp; &nbsp; &nbsp; &nbsp; api: __DIR__.'/../routes/api.php',<br>&nbsp; &nbsp; &nbsp; &nbsp; commands: __DIR__.'/../routes/console.php',<br>&nbsp; &nbsp; &nbsp; &nbsp; health: '/up',<br>&nbsp; &nbsp; )<br>&nbsp; &nbsp; -&gt;withMiddleware(function (Middleware $middleware) {<br>&nbsp; &nbsp; &nbsp; &nbsp; // Register your middleware<br>&nbsp; &nbsp; })<br>&nbsp; &nbsp; -&gt;withExceptions(function (Exceptions $exceptions) {<br>&nbsp; &nbsp; &nbsp; &nbsp; // Handle custom exceptions<br>&nbsp; &nbsp; })<br>&nbsp; &nbsp; -&gt;create();</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>But now, you can define routes <strong data-start="2186" data-end="2212">right inside this file</strong> using closures.</p>
<h3 data-start="2235" data-end="2298"><strong data-start="2242" data-end="2296">3. Defining Routes Directly in <code data-start="2275" data-end="2294">bootstrap/app.php</code></strong></h3>
<p data-start="2300" data-end="2364">Example of defining a route inline without creating <code data-start="2352" data-end="2361">web.php</code>:</p>
<p data-start="2300" data-end="2364">&lt;pre&gt;&lt;code&gt;</p>
<p>use Illuminate\Support\Facades\Route;<br>use Illuminate\Foundation\Application;</p>
<p>return Application::configure(basePath: dirname(__DIR__))<br>&nbsp; &nbsp; -&gt;withRouting(<br>&nbsp; &nbsp; &nbsp; &nbsp; using: function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::get('/', function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'Welcome to Laravel 12!';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::get('/about', function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'This is the about page.';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::get('/contact', function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'Contact us at support@example.com';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; )<br>&nbsp; &nbsp; -&gt;create();</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2941" data-end="2955">This method:</p>
<ul data-start="2956" data-end="3135">
<li data-start="2956" data-end="3028">
<p data-start="2958" data-end="3028">Removes the need for extra <code data-start="2985" data-end="3001">routes/web.php</code> or <code data-start="3005" data-end="3027">RouteServiceProvider</code>.</p>
</li>
<li data-start="3029" data-end="3051">
<p data-start="3031" data-end="3051">Speeds up boot time.</p>
</li>
<li data-start="3052" data-end="3135">
<p data-start="3054" data-end="3135">Keeps configuration and routes in one place &mdash; perfect for small or API-only apps.</p>
</li>
</ul>
<h3 data-start="3142" data-end="3192"><strong data-start="3149" data-end="3192">Combining Inline and External Routes</strong></h3>
<p data-start="3194" data-end="3273">If you still want to keep traditional route files, you can mix both approaches:</p>
<p data-start="3194" data-end="3273">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="3194" data-end="3273">return Application::configure(basePath: dirname(__DIR__))<br>&nbsp; &nbsp; -&gt;withRouting(<br>&nbsp; &nbsp; &nbsp; &nbsp; using: function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::get('/', fn() =&gt; 'Home Page');<br>&nbsp; &nbsp; &nbsp; &nbsp; },<br>&nbsp; &nbsp; &nbsp; &nbsp; web: __DIR__.'/../routes/web.php',<br>&nbsp; &nbsp; &nbsp; &nbsp; api: __DIR__.'/../routes/api.php'<br>&nbsp; &nbsp; )<br>&nbsp; &nbsp; -&gt;create();</p>
<p data-start="3194" data-end="3273">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="3194" data-end="3273">This gives you flexibility: define quick routes inline and load complex ones from files.</p>
<h3 data-start="3656" data-end="3700"><strong data-start="3663" data-end="3700">5. Why This Change in Laravel 12?</strong></h3>
<p data-start="3702" data-end="3770">Taylor Otwell introduced this cleaner structure for several reasons:</p>
<ul data-start="3771" data-end="3980">
<li data-start="3771" data-end="3822">
<p data-start="3773" data-end="3822"><strong data-start="3773" data-end="3789">Performance:</strong> Fewer service providers to boot.</p>
</li>
<li data-start="3823" data-end="3883">
<p data-start="3825" data-end="3883"><strong data-start="3825" data-end="3837">Clarity:</strong> All core app configuration lives in one file.</p>
</li>
<li data-start="3884" data-end="3980">
<p data-start="3886" data-end="3980"><strong data-start="3886" data-end="3902">Flexibility:</strong> Ideal for small services or when you want to customize how routes are loaded.</p>
</li>
</ul>
<h3 data-start="3987" data-end="4025"><strong data-start="3994" data-end="4025">6. Common Mistakes to Avoid</strong></h3>
<ol data-start="4026" data-end="4392">
<li data-start="4026" data-end="4132">
<p data-start="4029" data-end="4132"><strong data-start="4029" data-end="4062">Forgetting to import <code data-start="4052" data-end="4059">Route</code>:</strong><br data-start="4062" data-end="4065">Always add <code data-start="4079" data-end="4118">use Illuminate\Support\Facades\Route;</code> at the top.</p>
</li>
<li data-start="4133" data-end="4225">
<p data-start="4136" data-end="4225"><strong data-start="4136" data-end="4166">Misplacing closure syntax:</strong><br data-start="4166" data-end="4169">The closure for <code data-start="4188" data-end="4196">using:</code> must be properly enclosed.</p>
</li>
<li data-start="4226" data-end="4309">
<p data-start="4229" data-end="4309"><strong data-start="4229" data-end="4271">Missing trailing commas or parentheses</strong> can break your configuration chain.</p>
</li>
<li data-start="4310" data-end="4392">
<p data-start="4313" data-end="4392"><strong data-start="4313" data-end="4348">Mixing route groups incorrectly</strong> &mdash; wrap them properly if using middleware.</p>
</li>
</ol>
<p data-start="4394" data-end="4402">Example:</p>
<p data-start="4394" data-end="4402">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="4394" data-end="4402">Route::middleware('auth')-&gt;group(function () {<br>&nbsp; &nbsp; Route::get('/dashboard', fn() =&gt; 'Dashboard');<br>});</p>
<p data-start="4394" data-end="4402">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="4522" data-end="4578"><strong data-start="4529" data-end="4578">7. Example: API Routes in <code data-start="4557" data-end="4576">bootstrap/app.php</code></strong></h3>
<p data-start="4580" data-end="4621">You can also define API routes like this:</p>
<p data-start="4580" data-end="4621">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="4580" data-end="4621">return Application::configure(basePath: dirname(__DIR__))<br>&nbsp; &nbsp; -&gt;withRouting(<br>&nbsp; &nbsp; &nbsp; &nbsp; using: function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::prefix('api')-&gt;group(function () {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::get('/users', fn() =&gt; ['user' =&gt; 'John Doe']);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Route::post('/login', fn() =&gt; ['message' =&gt; 'Login success']);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; )<br>&nbsp; &nbsp; -&gt;create();</p>
<p data-start="4580" data-end="4621">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="4991" data-end="5090">This makes it super easy to build simple APIs without needing the full Laravel directory structure.</p>
<h3 data-start="5097" data-end="5117"><strong data-start="5103" data-end="5117">Conclusion</strong></h3>
<p data-start="5119" data-end="5384">Laravel 12 brings a fresh, modern approach to routing by allowing routes to be defined right in <code data-start="5215" data-end="5234">bootstrap/app.php</code>.<br data-start="5235" data-end="5238">This update simplifies project setup, improves flexibility, and makes Laravel more modular &mdash; especially useful for microservices and small apps.</p>
<p data-start="5386" data-end="5506">Whether you define routes inline or in separate files, Laravel 12 ensures smooth routing management with better control.</p>
<h2 data-start="6004" data-end="6048"><strong data-start="6009" data-end="6046">Frequently Asked Questions (FAQs)</strong></h2>
<h4 data-start="6050" data-end="6108"><strong data-start="6054" data-end="6106">1. Can I still use routes/web.php in Laravel 12?</strong></h4>
<p data-start="6109" data-end="6261">Yes, Laravel 12 still supports traditional route files. You can use both inline routes in <code data-start="6199" data-end="6218">bootstrap/app.php</code> and external route files simultaneously.</p>
<h4 data-start="6268" data-end="6332"><strong data-start="6272" data-end="6330">2. Why did Laravel move routes into bootstrap/app.php?</strong></h4>
<p data-start="6333" data-end="6470">The goal is to simplify application bootstrapping and improve performance by reducing provider overhead and centralizing configuration.</p>
<h4 data-start="6477" data-end="6548"><strong data-start="6481" data-end="6546">3. Is it necessary to define all routes in bootstrap/app.php?</strong></h4>
<p data-start="6549" data-end="6663">No. It&rsquo;s optional. You can keep using <code data-start="6587" data-end="6603">routes/web.php</code> and <code data-start="6608" data-end="6624">routes/api.php</code> if you prefer the classic structure.</p>
<h4 data-start="6670" data-end="6735"><strong data-start="6674" data-end="6733">4. Will this affect existing Laravel 10 or 11 projects?</strong></h4>
<p data-start="6736" data-end="6875">No. Older versions will keep using the previous structure. This change applies only if you upgrade to Laravel 12 and adopt the new setup.</p>
<h4 data-start="6882" data-end="6954"><strong data-start="6886" data-end="6952">5. Can I use middleware and route groups in bootstrap/app.php?</strong></h4>
<p data-start="6955" data-end="7087">Absolutely. Middleware, groups, and route parameters work exactly as before. Just make sure to import the <code data-start="7061" data-end="7068">Route</code> facade properly.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/QEGjywhBu2xoBhwTe4bJGLso68fIx13OJ917MGWQ.png" type="image/png" length="1296651" />
        <media:content url="https://manamil.dev/storage/uploads/posts/QEGjywhBu2xoBhwTe4bJGLso68fIx13OJ917MGWQ.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 10 Nov 2025 08:41:17 +0000</pubDate>

      
                        <category><![CDATA[Laravel 12 routing]]></category>
                  <category><![CDATA[bootstrap/app.php routes]]></category>
                  <category><![CDATA[Laravel routing guide]]></category>
                  <category><![CDATA[custom route files Laravel 12]]></category>
                  <category><![CDATA[web vs api routes Laravel]]></category>
                  <category><![CDATA[Laravel route configuration bootstrap]]></category>
                  <category><![CDATA[Laravel routing best practices]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Upgrading to Laravel 12 – Common Issues &amp; Solutions]]></title>
      <link>https://manamil.dev/blog/laravel/upgrading-to-laravel-12-common-issues</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/upgrading-to-laravel-12-common-issues</guid>

      
      <description><![CDATA[
        <p>Learn about the most common issues when upgrading to Laravel 12, including dependency conflicts, PHP version requirements, package compatibility, and testing strategies. A complete step-by-step guide with best practices.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/UqXnTsaDpCWIvfqJRhSOkkpK2ncIJPGqNJzWnOkJ.png" alt="Upgrading to Laravel 12 – Common Issues &amp; Solutions" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 dir="ltr">Introduction</h2>
<p dir="ltr">Upgrading a production Laravel application can be stressful &mdash; new framework versions bring performance improvements and helpful features, but they can also introduce breaking changes. <strong>Laravel 12</strong> modernizes routing, tightens minimum PHP requirements, updates the default frontend tooling, and removes/deprecates several helpers. If you plan and execute the upgrade carefully, you can avoid downtime and fix most issues quickly.</p>
<p dir="ltr">If you want to see the guidelines for installing Laravel, <a href="https://manamil.dev/../../../../blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide"><strong>click here.</strong></a></p>
<p dir="ltr">This guide walks you through a safe, step-by-step upgrade process from Laravel 11 (or earlier) to Laravel 12, highlights the most common problems developers face after upgrading, and provides concrete, copy-and-paste fixes. Follow these steps on a staging environment first, then apply them to production once everything is validated.</p>
<h2 dir="ltr">Step-by-Step Upgrade Guide</h2>
<p dir="ltr">Quick checklist before you start</p>
<ul>
<li dir="ltr" role="presentation">Create a backup of your repository and database.</li>
<li dir="ltr" role="presentation">Ensure you have a staging server that mirrors production.</li>
<li dir="ltr" role="presentation">Use version control (git) and create a feature branch for the upgrade.</li>
<li dir="ltr" role="presentation">Test thoroughly (unit, feature, and manual smoke tests).<br><br></li>
</ul>
<h3 dir="ltr">1. Review Laravel 12 Upgrade Notes &amp; Composer Constraints</h3>
<ol>
<li dir="ltr" aria-level="1">
<p dir="ltr" role="presentation">Read the official upgrade guide and CHANGELOG for Laravel 12 to identify breaking changes specific to your app (packages, helpers, events).</p>
</li>
<li dir="ltr" aria-level="1">
<p dir="ltr" role="presentation">Update your composer.json requirement for laravel/framework:</p>
</li>
</ol>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">"require": {<br>&nbsp; &nbsp; "laravel/framework": "^12.0",<br>&nbsp; &nbsp; // ... other deps<br>}</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Check third-party packages: ensure they support Laravel 12 or have new versions available.</p>
<h3 dir="ltr">2. Ensure PHP &amp; Server Requirements</h3>
<p dir="ltr">Laravel 12 requires PHP 8.2 or higher. Verify and upgrade PHP on your environment:</p>
<p dir="ltr">Check current PHP version</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php -v</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">&nbsp;</p>
<p dir="ltr">Ubuntu example (install PHP 8.2)</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">sudo apt update</p>
<p dir="ltr">sudo apt install php8.2 php8.2-fpm php8.2-cli php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-gd</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">If you are using managed hosting (Forge, Ploi, Vapor, shared hosting), confirm PHP 8.2 availability and select it.</p>
<p dir="ltr">&nbsp;</p>
<h3 dir="ltr">3. Update Composer Dependencies</h3>
<p dir="ltr">On your feature/staging branch:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">composer update<br>composer install --no-dev --optimize-autoloader</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">Fix any dependency conflicts by upgrading or replacing incompatible composer packages. If composer update fails, read the error message and update problematic packages in composer.json (or contact package maintainers).</p>
<h3 dir="ltr">4. Run Automated Tests &amp; Static Analysis</h3>
<p dir="ltr">Before changing code, run your test suite and static analysis tools:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php artisan test<br>./vendor/bin/phpstan analyse<br>./vendor/bin/pint&nbsp; # if using Laravel Pint</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">Fix failing tests that point to deprecated behavior or changed interfaces.</p>
<h3 dir="ltr">5. Update Routing Registration (bootstrap/app.php)</h3>
<p dir="ltr">Laravel 12 introduces a new pattern for registering route files in some project starter templates. If you used custom bootstrap code or a micro framework style, update it to the withRouting pattern where applicable.</p>
<p dir="ltr">Example new pattern:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">-&gt;withRouting(<br>&nbsp; &nbsp; web: __DIR__.'/../routes/web.php',<br>&nbsp; &nbsp; api: __DIR__.'/../routes/api.php',<br>&nbsp; &nbsp; console: __DIR__.'/../routes/console.php'<br>);</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">If your project still uses older routing group patterns, migrate to the current approach. Also search for custom $app-&gt;router-&gt;group() calls that might require updating.</p>
<h3 dir="ltr">6. Fix Model Namespaces &amp; Autoloading</h3>
<p dir="ltr">Laravel organizes models under app/Models by default. If your models live elsewhere or namespaces are incorrect:</p>
<ol>
<li dir="ltr" aria-level="1">
<p dir="ltr" role="presentation">Ensure model files have the correct namespace:<br><br></p>
</li>
</ol>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">namespace App\Models;</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Regenerate Composer autoload files:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">composer dump-autoload</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">If you moved files or renamed classes, update any references (type hints, factories, relationships).</p>
<h3 dir="ltr">7. Address Removed/Deprecated Methods</h3>
<p dir="ltr">Search your codebase for known removed helpers or methods (examples may include some previously available string or collection helpers). Replace with recommended alternatives from the Laravel docs or Illuminate helper classes.</p>
<p dir="ltr">Example<br>If you get:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">Call to undefined method Str::containsAll()</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">Replace with a custom helper or chain of Str::contains() calls, or update to the new method recommended in the upgrade notes.</p>
<h3 dir="ltr">8. Rebuild Frontend Assets (Vite)</h3>
<p dir="ltr">Laravel 12 uses Vite by default for asset bundling. After upgrade you should reinstall node modules and rebuild:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">npm ci<br># or<br>npm install</p>
<p dir="ltr"># development:<br>npm run dev</p>
<p dir="ltr"># production build:<br>npm run build</p>
<p dir="ltr">&lt;/pre&gt;&lt;/code&gt;</p>
<p dir="ltr">If you encounter &ldquo;Failed to resolve module&rdquo; errors, check your vite.config.js and resources/js/resources/css entry points for renamed paths.</p>
<h3 dir="ltr">9. Fix Storage Symlink Issues</h3>
<p dir="ltr">After upgrading, you may need to recreate the public storage link.</p>
<p dir="ltr">Remove old link (if present)</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">rm -rf public/storage</p>
<p dir="ltr">&lt;/pre&gt;&lt;/code&gt;</p>
<p dir="ltr">Create symlink</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php artisan storage:link</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">On some shared hosts, symlink creation may be restricted. In that case either enable symlinks in control panel or use a deployment step to copy files instead of linking.</p>
<h3 dir="ltr">10. Clear &amp; Rebuild Cache/Config</h3>
<p dir="ltr">Always clear caches after major upgrades to avoid stale cached configs and compiled classes:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php artisan optimize:clear<br>php artisan config:clear<br>php artisan route:clear<br>php artisan view:clear<br>composer dump-autoload -o</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">Then warm caches (optional):</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php artisan config:cache<br>php artisan route:cache</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">Note: only cache routes if your app does not rely on runtime route modifications (closures or dynamic route generation).</p>
<h3 dir="ltr">11. Verify Queues, Jobs &amp; Scheduler</h3>
<p dir="ltr">Laravel version changes can affect queue workers. Restart queue workers and verify job serialization compatibility:</p>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">php artisan queue:restart</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
<p dir="ltr">If you use serialized or versioned job classes, ensure __serialize()/__unserialize() compatibility or migrate job payloads before starting workers.</p>
<h3 dir="ltr">12. Update Docs, Policies &amp; Tests</h3>
<ul>
<li dir="ltr" role="presentation">Update documentation for your team to note Laravel 12 specifics.</li>
<li dir="ltr" role="presentation">Update CI pipeline to use PHP 8.2 in test matrix.</li>
<li dir="ltr" role="presentation">Run integration tests on staging to confirm user flows.<br><br></li>
</ul>
<h3 dir="ltr">13. Deploy to Production (after staging is clean)</h3>
<ul>
<li>Merge the upgrade branch to your release branch.</li>
<li>Deploy to a maintenance window or zero-downtime deployment if possible.</li>
<li>Run post-deploy steps:<br>
<p dir="ltr">&lt;pre&gt;&lt;code&gt;</p>
<p dir="ltr">composer install --no-dev --optimize-autoloader</p>
<p dir="ltr">php artisan migrate --force&nbsp; &nbsp; &nbsp; # if DB migrations are required</p>
<p dir="ltr">php artisan storage:link</p>
<p dir="ltr">php artisan optimize:clear</p>
<p dir="ltr">php artisan config:cache</p>
<p dir="ltr">php artisan route:cache</p>
<p dir="ltr">npm ci &amp;&amp; npm run build&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # if assets are built on server</p>
<p dir="ltr">&lt;/code&gt;&lt;/pre&gt;</p>
</li>
</ul>
<p dir="ltr">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Monitor logs and error reporting tools (Sentry, Bugsnag, Papertrail) for a few hours after deployment.</p>
<h2 dir="ltr">Common Problems &amp; Exact Fixes (Quick Reference)</h2>
<ul>
<li dir="ltr" role="presentation">Composer conflicts: Update packages or remove incompatible ones; check package GitHub for Laravel 12 compatibility.</li>
<li dir="ltr" role="presentation">PHP version errors: Upgrade to PHP 8.2+ on all environments.</li>
<li dir="ltr" role="presentation">Route not defined or routing failures: Update bootstrap routing registration and remove deprecated group code.</li>
<li dir="ltr" role="presentation">Target class does not exist: Fix model/controller namespaces, run composer dump-autoload.</li>
<li dir="ltr" role="presentation">Storage symlink errors: rm -rf public/storage &amp;&amp; php artisan storage:link.</li>
<li dir="ltr" role="presentation">Vite asset errors: npm ci + npm run build; check vite.config.js and entry paths.</li>
<li dir="ltr" role="presentation">500 errors after deploy: php artisan optimize:clear and check .env correctness.</li>
<li dir="ltr" role="presentation">Queue serialization issues: Restart workers and confirm job class compatibility.<br><br></li>
</ul>
<h2 dir="ltr">FAQs</h2>
<p dir="ltr"><strong>Q1 &mdash; Should I upgrade immediately?</strong><br>A: Not unless you need Laravel 12 features or security fixes. Upgrade on a controlled schedule &mdash; test on staging first, and ensure package compatibility.</p>
<p dir="ltr"><strong>Q2 &mdash; Do I need to update PHP on both dev and prod?</strong><br>A: Yes. PHP 8.2 is required. Update local dev, CI, staging, and production to avoid environment mismatches.</p>
<p dir="ltr"><strong>Q3 &mdash; My php artisan storage:link shows permission or symlink errors. What now?</strong><br>A: Remove the existing public/storage folder/link, then run php artisan storage:link. If still blocked, check file permissions and hosting control panel settings (some shared hosts block symlinks). As a fallback, copy storage/app/public to public/storage during deployment.</p>
<p dir="ltr"><strong>Q4 &mdash; After upgrading, my assets are missing.</strong><br>A: Rebuild assets with npm install / npm ci and npm run build. Ensure vite.config.js entry points match your resources/ paths and that @vite directive is used in your Blade layout.</p>
<p dir="ltr"><strong>Q5 &mdash; Should I cache config and routes after upgrading?</strong><br>A: Yes in production for performance, but only after verifying everything works. Remember to run php artisan optimize:clear if issues appear and only route:cache if your routes are static (no closures).</p>
<p dir="ltr"><strong>Q6 &mdash; Third-party packages not compatible with Laravel 12 &mdash; what should I do?</strong><br>A: Check for package updates or forks that support Laravel 12. If none exist, consider replacing the package with an actively maintained alternative or implement the needed functionality in-house.</p>
<p dir="ltr"><strong>Q7 &mdash; Any special advice for Laravel Vapor or serverless environments?</strong><br>A: Vapor usually supports the latest Laravel versions quickly, but always confirm Vapor CLI and runtime PHP versions in the Vapor docs. Run a full Vapor deployment on a test environment before production.</p>
<p dir="ltr"><strong>Q8 &mdash; How do I rollback if something goes wrong?</strong><br>A: Use your version control revert/rollback procedures and database backups. If you used zero-downtime deploys, roll back via your deploy tooling (Forge, Envoyer, GitHub Actions). Ensure DB migrations are reversible or use backups.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/UqXnTsaDpCWIvfqJRhSOkkpK2ncIJPGqNJzWnOkJ.png" type="image/png" length="1122598" />
        <media:content url="https://manamil.dev/storage/uploads/posts/UqXnTsaDpCWIvfqJRhSOkkpK2ncIJPGqNJzWnOkJ.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 10 Nov 2025 08:39:40 +0000</pubDate>

      
                        <category><![CDATA[Laravel 12 upgrade]]></category>
                  <category><![CDATA[Laravel version upgrade issues]]></category>
                  <category><![CDATA[Laravel 12 common problems]]></category>
                  <category><![CDATA[upgrading Laravel 12 tips]]></category>
                  <category><![CDATA[Laravel 12 PHP 8.2 compatibility]]></category>
                  <category><![CDATA[Laravel dependency conflicts]]></category>
                  <category><![CDATA[Laravel 12 breaking changes]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Laravel 12 Social &amp; Passkey Authentication (AuthKit) – Complete Guide]]></title>
      <link>https://manamil.dev/blog/laravel/laravel%E2%80%9112%E2%80%90social%E2%80%91passkey%E2%80%90authentication%E2%80%91authkit</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel%E2%80%9112%E2%80%90social%E2%80%91passkey%E2%80%90authentication%E2%80%91authkit</guid>

      
      <description><![CDATA[
        <p>Discover how to integrate social login, passkey (WebAuthn) authentication and enterprise‑ready SSO with WorkOS AuthKit in Laravel 12. Step‑by‑step setup, best practices and security insights.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/SiP71jsJv0MVBM01l09pjyfd2oLnAps0porV2kDB.png" alt="Laravel 12 Social &amp; Passkey Authentication (AuthKit) – Complete Guide" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2><strong>Introduction to Modern Authentication {#introduction}</strong></h2>
<p data-start="621" data-end="769">Laravel 12 brings a more powerful and flexible authentication system than ever before. Along with traditional email/password login, it now supports:</p>
<ul>
<li data-start="773" data-end="829">Social authentication (Google, GitHub, Facebook, etc.)</li>
<li data-start="832" data-end="864">Modern passkeys using WebAuthn</li>
<li data-start="867" data-end="899">Passwordless login experiences</li>
<li data-start="902" data-end="955">AuthKit starter with built-in SSO + passkey support</li>
</ul>
<p data-start="957" data-end="1133">This guide explains how to implement both <strong data-start="999" data-end="1015">Social Login</strong> and <strong data-start="1020" data-end="1046">Passkey authentication</strong> in a clean, production-ready way that you can directly use in your Laravel 12 project.</p>
<h2 data-start="1140" data-end="1178"><strong data-start="1142" data-end="1178">Why Use Social Login + Passkeys?</strong></h2>
<h3 data-start="1180" data-end="1212"><strong data-start="1184" data-end="1212">Benefits of Social Login</strong></h3>
<ul>
<li data-start="1215" data-end="1247">Quick and frictionless sign-up</li>
<li data-start="1250" data-end="1290">Users don&rsquo;t need to remember passwords</li>
<li data-start="1293" data-end="1319">Verified email addresses</li>
<li data-start="1322" data-end="1348">Reduced support overhead</li>
</ul>
<h3 data-start="1350" data-end="1389"><strong data-start="1354" data-end="1389">Benefits of Passkeys (WebAuthn)</strong></h3>
<ul>
<li data-start="1392" data-end="1415">No passwords required</li>
<li data-start="1418" data-end="1438">Immune to phishing</li>
<li data-start="1441" data-end="1465">Extremely hard to hack</li>
<li data-start="1468" data-end="1536">Works with Face ID, Touch ID, Windows Hello, Android security keys</li>
</ul>
<p data-start="1538" data-end="1613">Combining both provides users a secure, seamless authentication experience.</p>
<h2><strong>What is AuthKit?</strong></h2>
<p class="ds-markdown-paragraph">AuthKit is a comprehensive authentication package for Laravel that provides:</p>
<ul>
<li class="ds-markdown-paragraph">Social authentication (Google, GitHub, Facebook, Twitter)</li>
<li class="ds-markdown-paragraph">Passkey/WebAuthn support</li>
<li class="ds-markdown-paragraph">Multi-factor authentication</li>
<li class="ds-markdown-paragraph">Session management</li>
<li class="ds-markdown-paragraph">Security monitoring</li>
</ul>
<h2><strong>Prerequisites</strong></h2>
<p class="ds-markdown-paragraph">Before we begin, ensure you have:</p>
<ul>
<li class="ds-markdown-paragraph">PHP 8.2+ installed</li>
<li class="ds-markdown-paragraph"><span style="text-decoration: underline;"><a title="https://manamil.dev/blog/laravel/how-to-install-composer-for-ubuntu-and-windows-step-by-step-guide" href="https://manamil.dev/../../../../blog/laravel/how-to-install-composer-for-ubuntu-and-windows-step-by-step-guide">Composer</a></span> globally installed</li>
<li class="ds-markdown-paragraph">Laravel 12 installed</li>
<li class="ds-markdown-paragraph">A database (MySQL/PostgreSQL/SQLite)</li>
<li class="ds-markdown-paragraph">Text editor/IDE</li>
</ul>
<h2 data-start="1620" data-end="1655"><strong>Setup Paths You Can Choose</strong></h2>
<p style="line-height: 1;" data-start="1657" data-end="1703">Laravel 12 allows three authentication setups:</p>
<h3 style="line-height: 1;" data-start="1705" data-end="1751"><strong data-start="1709" data-end="1749">1. AuthKit (Fastest &amp; Most Complete)</strong></h3>
<p style="line-height: 1;" data-start="1752" data-end="1812">Ready-made authentication including passkeys + social login.</p>
<h3 style="line-height: 1;" data-start="1814" data-end="1869"><strong data-start="1818" data-end="1867">2. Socialite + WebAuthn Package (Self-Hosted)</strong></h3>
<p style="line-height: 1;" data-start="1870" data-end="1909">Maximum control and fully customizable.</p>
<h3 style="line-height: 1;" data-start="1911" data-end="1971"><strong data-start="1915" data-end="1969">3. Hosted Passkey Services (Easiest Passkey Setup)</strong></h3>
<p style="line-height: 1;" data-start="1972" data-end="2011">Use a third-party service for WebAuthn.</p>
<p style="line-height: 1;" data-start="2013" data-end="2076">Below you'll find step-by-step instructions for all approaches.</p>
<h2 data-start="2083" data-end="2149"><strong data-start="2087" data-end="2149">Option A: Laravel 12 AuthKit (Recommended Beginner Option)</strong></h2>
<p data-start="2151" data-end="2232">AuthKit is a modern authentication starter included with Laravel 12. It provides:</p>
<ul>
<li data-start="2236" data-end="2258">Social Login buttons</li>
<li data-start="2261" data-end="2287">Passkey/WebAuthn support</li>
<li data-start="2290" data-end="2320">Registration and login pages</li>
<li data-start="2323" data-end="2348">Email/password fallback</li>
<li data-start="2351" data-end="2368">User management</li>
</ul>
<h3 data-start="2370" data-end="2428"><strong data-start="2374" data-end="2428">Step 1 &mdash; Create a New Laravel Project with AuthKit</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>laravel new projectname</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>Choose <strong data-start="2472" data-end="2483">AuthKit</strong> during installation.</p>
<h3 data-start="2506" data-end="2548"><strong data-start="2510" data-end="2548">Step 2 &mdash; Add Environment Variables</strong></h3>
<p data-start="2549" data-end="2559">In <code data-start="2552" data-end="2558">.env</code>:</p>
<p data-start="2549" data-end="2559">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2549" data-end="2559">AUTHKIT_CLIENT_ID=xxxx<br>AUTHKIT_SECRET=xxxx<br>AUTHKIT_REDIRECT=https://yourdomain.com/auth/callback</p>
<p data-start="2549" data-end="2559">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="2666" data-end="2717"><strong data-start="2670" data-end="2717">Step 3 &mdash; AuthKit Provides Ready-Made Routes</strong></h3>
<ul>
<li data-start="2720" data-end="2730"><code data-start="2720" data-end="2728">/login</code></li>
<li data-start="2733" data-end="2746"><code data-start="2733" data-end="2744">/register</code></li>
<li data-start="2749" data-end="2772"><code data-start="2749" data-end="2770">/auth/social/google</code></li>
<li data-start="2775" data-end="2797"><code data-start="2775" data-end="2795">/passkeys/register</code></li>
<li data-start="2800" data-end="2819"><code data-start="2800" data-end="2817">/passkeys/login</code></li>
</ul>
<h3 data-start="2821" data-end="2866"><strong data-start="2825" data-end="2866">Step 4 &mdash; Add Frontend Buttons (Blade)</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;<br>&amp;lt;a href=&amp;quot;/auth/social/google&amp;quot; class=&amp;quot;btn btn-google&amp;quot;&amp;gt;Login with Google&amp;lt;/a&amp;gt;<br>&amp;lt;a href=&amp;quot;/auth/social/github&amp;quot; class=&amp;quot;btn btn-github&amp;quot;&amp;gt;Login with GitHub&amp;lt;/a&amp;gt;</p>
<p>&amp;lt;button id=&amp;quot;passkey-login&amp;quot;&amp;gt;Use Passkey&amp;lt;/button&amp;gt;<br>&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="3079" data-end="3120"><strong data-start="3083" data-end="3120">Step 5 &mdash; Built-in JS for Passkeys</strong></h3>
<p data-start="3121" data-end="3219">AuthKit includes JavaScript helpers for WebAuthn registration and login &mdash; no heavy setup required.</p>
<h2 data-start="3226" data-end="3285"><strong data-start="3230" data-end="3285">Option B: Socialite + WebAuthn (Fully Custom Setup)</strong></h2>
<p data-start="3287" data-end="3382">If you want full control or do not want to rely on a hosted solution, this is your best choice.</p>
<hr data-start="3384" data-end="3387">
<h2 data-start="3389" data-end="3432"><strong data-start="3391" data-end="3432">Part 1 &mdash; Social Login using Socialite</strong></h2>
<h3 data-start="3434" data-end="3468"><strong data-start="3438" data-end="3468">Step 1 &mdash; Install Socialite</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>composer require laravel/socialite</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="3517" data-end="3552"><strong data-start="3521" data-end="3552">Step 2 &mdash; Configure Provider</strong></h3>
<p data-start="3553" data-end="3575"><code data-start="3553" data-end="3574">config/services.php</code>:</p>
<p data-start="3553" data-end="3575">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="3553" data-end="3575">'google' =&gt; [<br>&nbsp; &nbsp; 'client_id' =&gt; env('GOOGLE_CLIENT_ID'),<br>&nbsp; &nbsp; 'client_secret' =&gt; env('GOOGLE_CLIENT_SECRET'),<br>&nbsp; &nbsp; 'redirect' =&gt; env('GOOGLE_REDIRECT'),<br>],</p>
<p data-start="3553" data-end="3575">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="3553" data-end="3575"><strong>Step 3 &mdash; Add Routes</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>Route::get('/login/{provider}', function ($provider) {<br>&nbsp; &nbsp; return Socialite::driver($provider)-&gt;redirect();<br>});</p>
<p>Route::get('/login/{provider}/callback', [SocialController::class, 'handle']);</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3><strong>Step 4 &mdash; Controller</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>class SocialController<br>{<br>&nbsp; &nbsp; public function handle($provider)<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; $socialUser = Socialite::driver($provider)-&gt;user();</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; $user = User::firstOrCreate(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ['email' =&gt; $socialUser-&gt;getEmail()],<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ['name' =&gt; $socialUser-&gt;getName()]<br>&nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; Auth::login($user);</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; return redirect('/');<br>&nbsp; &nbsp; }<br>}</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>}<br>This completes social authentication.</p>
<h2 data-start="4402" data-end="4450"><strong data-start="4404" data-end="4450">Part 2 &mdash; Passkey (WebAuthn) Authentication</strong></h2>
<p data-start="4452" data-end="4512">You can use any of the well-known Laravel WebAuthn packages.</p>
<h3 data-start="4514" data-end="4559"><strong data-start="4517" data-end="4559">Step 1 &mdash; Install Your WebAuthn Package</strong></h3>
<p data-start="4560" data-end="4568">Example:</p>
<p data-start="4560" data-end="4568">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="4560" data-end="4568">composer require vendor/webauthn</p>
<p data-start="4560" data-end="4568">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="4560" data-end="4568"><strong>Step 2 &mdash; Publish &amp; Migrate</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>php artisan vendor:publish --tag=webauthn<br>php artisan migrate</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3><strong>Step 3 &mdash; Generate Registration Challenge</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>public function createPasskeyOptions(Request $request)<br>{<br>&nbsp; &nbsp; $options = WebAuthn::prepareCreate($request-&gt;user());<br>&nbsp; &nbsp; session(['passkey_registration' =&gt; $options]);</p>
<p>&nbsp; &nbsp; return response()-&gt;json($options);<br>}</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3><strong>Step 4 &mdash; Verify Attestation</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>public function verifyPasskey(Request $request)<br>{<br>&nbsp; &nbsp; $verified = WebAuthn::validateCreate(<br>&nbsp; &nbsp; &nbsp; &nbsp; $request-&gt;input(),<br>&nbsp; &nbsp; &nbsp; &nbsp; session('passkey_registration'),<br>&nbsp; &nbsp; &nbsp; &nbsp; $request-&gt;user()<br>&nbsp; &nbsp; );</p>
<p>&nbsp; &nbsp; return $verified<br>&nbsp; &nbsp; &nbsp; &nbsp; ? response()-&gt;json(['success' =&gt; true])<br>&nbsp; &nbsp; &nbsp; &nbsp; : response()-&gt;json(['error' =&gt; 'Verification failed'], 422);<br>}</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h2><strong>Frontend JavaScript (Passkey Registration Example)</strong></h2>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>&lt;button id="register-passkey"&gt;Register Passkey&lt;/button&gt;</p>
<p>&lt;script&gt;<br>document.getElementById("register-passkey").onclick = async () =&gt; {</p>
<p>&nbsp; &nbsp; const res = await fetch('/passkeys/options', {<br>&nbsp; &nbsp; &nbsp; &nbsp; method: "POST",<br>&nbsp; &nbsp; &nbsp; &nbsp; headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }<br>&nbsp; &nbsp; });</p>
<p>&nbsp; &nbsp; const options = await res.json();<br>&nbsp; &nbsp; options.publicKey.challenge = Uint8Array.from(atob(options.publicKey.challenge), c =&gt; c.charCodeAt(0));</p>
<p>&nbsp; &nbsp; const credential = await navigator.credentials.create(options);</p>
<p>&nbsp; &nbsp; await fetch('/passkeys/verify', {<br>&nbsp; &nbsp; &nbsp; &nbsp; method: "POST",<br>&nbsp; &nbsp; &nbsp; &nbsp; headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },<br>&nbsp; &nbsp; &nbsp; &nbsp; body: JSON.stringify(credential)<br>&nbsp; &nbsp; });</p>
<p>&nbsp; &nbsp; alert("Passkey registered successfully!");<br>};<br>&lt;/script&gt;</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h1 data-start="6213" data-end="6239"><strong data-start="6215" data-end="6239">User Experience Tips</strong></h1>
<ul>
<li>Provide all login options on the same screen</li>
<li>Recommend passkeys for returning users</li>
<li>Allow users to add multiple passkeys (laptop + phone)</li>
<li>Provide delete/rename options for passkeys</li>
</ul>
<h1 data-start="6444" data-end="6473"><strong data-start="6446" data-end="6473">Security Best Practices</strong></h1>
<ul>
<li data-start="6477" data-end="6520">Always use HTTPS &mdash; mandatory for WebAuthn</li>
<li data-start="6523" data-end="6564">Keep RPID (Relying Party ID) consistent</li>
<li data-start="6567" data-end="6605">Use rate limiting for login requests</li>
<li data-start="6608" data-end="6660">Store only the <strong data-start="6623" data-end="6637">public key</strong>, not the private key</li>
<li data-start="6663" data-end="6707">Use fallback login (email/password or OTP)</li>
</ul>
<h2><strong>Common Problems &amp; Solutions</strong></h2>
<table style="height: 179px; width: 93.6321%;">
<thead>
<tr style="height: 33px;">
<th style="width: 31.0257%;">Problem</th>
<th style="width: 21.0642%;">Cause</th>
<th style="width: 42.5771%;">Solution</th>
</tr>
</thead>
<tbody>
<tr style="height: 36px;">
<td style="width: 31.0257%;">WebAuthn not working locally</td>
<td style="width: 21.0642%;">No HTTPS</td>
<td style="width: 42.5771%;">Use local certificate or staging domain</td>
</tr>
<tr style="height: 36px;">
<td style="width: 31.0257%;">OAuth redirect mismatch</td>
<td style="width: 21.0642%;">Wrong redirect URL</td>
<td style="width: 42.5771%;">Add the correct URL in provider settings</td>
</tr>
<tr style="height: 36px;">
<td style="width: 31.0257%;">Passkey fails to verify</td>
<td style="width: 21.0642%;">Incorrect challenge</td>
<td style="width: 42.5771%;">Ensure session challenge matches client</td>
</tr>
<tr style="height: 37px;">
<td style="width: 31.0257%;">Google returns no email</td>
<td style="width: 21.0642%;">Missing scope</td>
<td style="width: 42.5771%;">Add <code>email</code> scope in Socialite</td>
</tr>
</tbody>
</table>
<h2 data-start="7163" data-end="7173"><strong data-start="7165" data-end="7173">FAQs</strong></h2>
<h3 data-start="7175" data-end="7233"><strong data-start="7179" data-end="7231">1. Can I use social login and passkeys together?</strong></h3>
<p data-start="7234" data-end="7292">Yes. Both methods can exist side-by-side without conflict.</p>
<h3 data-start="7294" data-end="7348"><strong data-start="7298" data-end="7346">2. Do passkeys completely replace passwords?</strong></h3>
<p data-start="7349" data-end="7406">They can, but it&rsquo;s recommended to keep a fallback option.</p>
<h3 data-start="7408" data-end="7452"><strong data-start="7412" data-end="7450">3. Which devices support passkeys?</strong></h3>
<p data-start="7453" data-end="7541">iPhone, Android, macOS, Windows Hello, Chrome, Edge, Safari &mdash; almost all modern devices.</p>
<h3 data-start="7543" data-end="7579"><strong data-start="7547" data-end="7577">4. Is social login secure?</strong></h3>
<p data-start="7580" data-end="7634">Yes. Major providers already verify users&rsquo; identities.</p>
<h3 data-start="7636" data-end="7696"><strong data-start="7640" data-end="7694">5. Does WebAuthn store private keys on the server?</strong></h3>
<p data-start="7697" data-end="7748">No. The private key never leaves the user&rsquo;s device.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/SiP71jsJv0MVBM01l09pjyfd2oLnAps0porV2kDB.png" type="image/png" length="1257113" />
        <media:content url="https://manamil.dev/storage/uploads/posts/SiP71jsJv0MVBM01l09pjyfd2oLnAps0porV2kDB.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 10 Nov 2025 08:37:13 +0000</pubDate>

      
                        <category><![CDATA[Laravel 12]]></category>
                  <category><![CDATA[AuthKit]]></category>
                  <category><![CDATA[WorkOS AuthKit]]></category>
                  <category><![CDATA[social authentication Laravel]]></category>
                  <category><![CDATA[passkey authentication Laravel]]></category>
                  <category><![CDATA[WebAuthn Laravel]]></category>
                  <category><![CDATA[Laravel SSO]]></category>
                  <category><![CDATA[passwordless login Laravel]]></category>
                  <category><![CDATA[Laravel starter kit AuthKit]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Getting Started with Laravel 12 Starter Kits (React/Vue/Livewire)]]></title>
      <link>https://manamil.dev/blog/laravel/laravel-12-starter-kits-react-vue-livewire</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel-12-starter-kits-react-vue-livewire</guid>

      
      <description><![CDATA[
        <p>Learn how to set up Laravel 12 with React, Vue, or Livewire starter kits. Step-by-step guide with Vite, Tailwind, and shadcn/ui.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/5bWChQhsR2bsyWlNh67FJIfO8X6zEdVD4dWFwwhj.png" alt="Getting Started with Laravel 12 Starter Kits (React/Vue/Livewire)" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2><strong>Introduction</strong></h2>
<p data-start="73" data-end="393">We want to help you start your new Laravel application easily. That&rsquo;s why we offer <a title="application starter kits" href="https://laravel.com/starter-kits" target="_blank" rel="noopener"><span style="text-decoration: underline;"><strong data-start="175" data-end="191">starter kits</strong></span></a>. These kits give you a ready-made structure with routes, controllers, and views. They help you set up user registration and login quickly. The starter kits use <a title="Laravel Fortify" href="https://laravel.com/docs/12.x/fortify" target="_blank" rel="noopener"><span style="text-decoration: underline;"><strong data-start="352" data-end="371">Laravel Fortify</strong></span></a> for authentication.</p>
<p data-start="395" data-end="603">You don&rsquo;t have to use the starter kits if you don&rsquo;t want to. You can also create your application from scratch by installing a fresh copy of Laravel. Either way, we are sure you will make something amazing!</p>
<h2 data-start="395" data-end="603"><strong>Why use a Starter Kit?</strong></h2>
<ul>
<li>Before diving in, let&rsquo;s clarify what these kits give you and why you might choose one:</li>
<li>They scaffold a full authentication system (login/register/password reset/email verification) out of the box.</li>
<li>They come pre‑wired with front‑end tooling (inertia, Vite, Tailwind CSS) so you spend less time wiring things.</li>
<li>They allow you to pick your preferred front‑end stack (React/Vue/Livewire) and still leverage Laravel&rsquo;s backend.</li>
<li>If you don&rsquo;t need one of these, you can still choose &ldquo;None&rdquo; and install your own (or use older kits like Breeze/Jetstream).</li>
</ul>
<h2><strong>Choosing Which Kit: React vs Vue vs Livewire</strong></h2>
<table style="width: 100%; height: 192.281px;">
<thead>
<tr style="height: 33.375px;">
<th style="text-align: left; width: 5.68666%;">Kit</th>
<th style="width: 26.5018%; text-align: left;">Front-end Stack</th>
<th style="width: 41.6836%; text-align: left;">Best For</th>
<th style="width: 26.1279%; text-align: left;">Notes</th>
</tr>
</thead>
<tbody>
<tr style="height: 52.9688px;">
<td style="width: 5.68666%;"><strong>React</strong></td>
<td style="width: 26.5018%;">React (with TypeScript), Inertia, Tailwind</td>
<td style="width: 41.6836%;">If you know React, want a fast Single Page App (SPA) feel, and like JavaScript tools</td>
<td style="width: 26.1279%;">Uses Inertia to connect Laravel with React.</td>
</tr>
<tr style="height: 52.9688px;">
<td style="width: 5.68666%;"><strong>Vue</strong></td>
<td style="width: 26.5018%;">Vue 3 (Composition API), TypeScript, Inertia, Tailwind</td>
<td style="width: 41.6836%;">If you prefer Vue and want a SPA experience</td>
<td style="width: 26.1279%;">Also uses Inertia for Laravel integration.</td>
</tr>
<tr style="height: 52.9688px;">
<td style="width: 5.68666%;"><strong>Livewire</strong></td>
<td style="width: 26.5018%;">Livewire 3, Blade templates, Tailwind, Flux UI</td>
<td style="width: 41.6836%;">If you want to stay mostly in PHP/Blade with minimal JavaScript</td>
<td style="width: 26.1279%;">Works like traditional Laravel but gives a reactive UI.</td>
</tr>
</tbody>
</table>
<p><strong data-start="2315" data-end="2323"><strong data-start="43" data-end="51">Tip:</strong> </strong>If you are not very experienced with front-end frameworks and want a fast backend-driven UI, <strong>Livewire</strong> might be a better choice. If you want the full JavaScript ecosystem, go with <strong>React</strong> or <strong>Vue</strong>.</p>
<h2><strong>Step‑by‑Step: Installing a Starter Kit</strong></h2>
<p><strong>Step 1: Install a Fresh Laravel Project</strong></p>
<p>First, you need a new Laravel application. Open your terminal and run:</p>
<p>&lt;pre&gt;&lt;code&gt;composer create-project laravel/laravel my-app&lt;/code&gt;&lt;/pre&gt;</p>
<p>Replace <code data-start="345" data-end="353">my-app</code> with your project name. This will create a new Laravel application with all the basic files.</p>
<h2>Step 2: Go to Your Project Folder</h2>
<p>&lt;pre&gt;&lt;code&gt;cd my-app&lt;/code&gt;&lt;/pre&gt;</p>
<p>This moves you into your project directory so you can start installing the starter kit.</p>
<h2><strong>Step 3: Choose a Starter Kit</strong></h2>
<p>Decide which starter kit you want to use:</p>
<ul>
<li data-start="697" data-end="785"><strong data-start="697" data-end="718">React Starter Kit</strong> &ndash; if you like React and want a SPA (Single Page App) experience.</li>
<li data-start="788" data-end="856"><strong data-start="788" data-end="807">Vue Starter Kit</strong> &ndash; if you prefer Vue and want a SPA experience.</li>
<li data-start="859" data-end="952"><strong data-start="859" data-end="883">Livewire Starter Kit</strong> &ndash; if you want to stay mostly in PHP/Blade and minimize JavaScript.</li>
</ul>
<h2><strong>Step 4: Install the Starter Kit</strong></h2>
<p>Use Composer to install your chosen kit. For example:</p>
<ul>
<li><strong data-start="1056" data-end="1080">Livewire Starter Kit</strong>:</li>
<li>&lt;pre&gt;&lt;code&gt;composer require laravel/jetstream<br>php artisan jetstream:install livewire&lt;/code&gt;&lt;/pre&gt;</li>
<li><strong data-start="1174" data-end="1195">React Starter Kit</strong>:</li>
<li>&lt;pre&gt;&lt;code&gt;composer require laravel/jetstream<br>php artisan jetstream:install inertia --teams&lt;/code&gt;&lt;/pre&gt;</li>
<li><strong data-start="1296" data-end="1315">Vue Starter Kit</strong>:</li>
<li>&lt;pre&gt;&lt;code&gt;composer require laravel/jetstream<br>php artisan jetstream:install inertia&lt;/code&gt;&lt;/pre&gt;</li>
</ul>
<p>Note: The <code data-start="1418" data-end="1427">--teams</code> option is only needed if you want team features.</p>
<h2><strong>Step 5: Install NPM Packages</strong></h2>
<p data-start="1485" data-end="1612">After installing the kit, install front-end dependencies using NPM (Node Package Manager):</p>
<p data-start="1485" data-end="1612">&lt;pre&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1485" data-end="1612">Then compile the assets:</p>
<p data-start="1485" data-end="1612">&lt;pre&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1692" data-end="1774">This will compile your CSS and JavaScript files so the front-end works properly.</p>
<h2 data-start="1692" data-end="1774">Step 6: Set Up Your Database</h2>
<p>Open the <code data-start="2362" data-end="2368">.env</code> file in your project folder. Set these values according to your database:</p>
<p>&lt;pre&gt;&lt;code&gt;DB_DATABASE=your_database_name<br>DB_USERNAME=your_db_username<br>DB_PASSWORD=your_db_password<br>&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2542" data-end="2562">Then run migrations:</p>
<p data-start="2542" data-end="2562">&lt;pre&gt;&lt;code&gt;php artisan migrate&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2597" data-end="2663">This creates all the tables your app needs (users, teams, etc.).</p>
<h2 data-start="2670" data-end="2702"><strong data-start="2674" data-end="2702">Step 7: Start the Server</strong></h2>
<p data-start="2703" data-end="2746">Run this command to start your Laravel app:</p>
<p data-start="2703" data-end="2746">&lt;pre&gt;&lt;code&gt;php artisan serve&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2703" data-end="2746">Open your browser and go to:</p>
<p data-start="2703" data-end="2746">&lt;pre&gt;&lt;code&gt;http://127.0.0.1:8000&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2840" data-end="2909">You should see your new Laravel app with the starter kit installed.</p>
<h2 data-start="2916" data-end="2964"><strong data-start="2920" data-end="2964">Step 8: Test User Registration and Login</strong></h2>
<ul>
<li data-start="2967" data-end="3010">Click &ldquo;Register&rdquo; to create a new account.</li>
<li data-start="3013" data-end="3040">Log in with your account.</li>
<li data-start="3043" data-end="3100">All starter kits come with ready-to-use authentication.</li>
</ul>
<p><strong data-start="3109" data-end="3129">Congratulations!</strong> You now have a fully working Laravel app with a starter kit. From here, you can start building your features.</p>
<p><img src="https://manamil.dev/../../../../storage/gallery/img/DQeTB6hCOip75J8ZBz2Gmanamil-dev.png" alt="" width="533" height="800"></p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/5bWChQhsR2bsyWlNh67FJIfO8X6zEdVD4dWFwwhj.png" type="image/png" length="677305" />
        <media:content url="https://manamil.dev/storage/uploads/posts/5bWChQhsR2bsyWlNh67FJIfO8X6zEdVD4dWFwwhj.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 10 Nov 2025 08:35:03 +0000</pubDate>

      
                        <category><![CDATA[laravel 12 starter kits]]></category>
                  <category><![CDATA[laravel 12 vue starter kit]]></category>
                  <category><![CDATA[laravel 12 react starter kit]]></category>
                  <category><![CDATA[laravel 12 livewire starter kit]]></category>
                  <category><![CDATA[laravel 12 starter kits tutorial]]></category>
                  <category><![CDATA[vite laravel 12]]></category>
                  <category><![CDATA[tailwind laravel 12]]></category>
                  <category><![CDATA[shadcn ui laravel 12]]></category>
                  <category><![CDATA[inertia js laravel 12]]></category>
                  <category><![CDATA[laravel frontend setup]]></category>
                  </item>
      
    <item>
      <title><![CDATA[How to Install Free SSL on Ubuntu Server Using Certbot (Step-by-Step 2026 Guide)]]></title>
      <link>https://manamil.dev/blog/laravel/how-to-install-free-ssl-on-ubuntu-server-using-certbot-step-by-step-2026-guide</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/how-to-install-free-ssl-on-ubuntu-server-using-certbot-step-by-step-2026-guide</guid>

      
      <description><![CDATA[
        <p>Secure your Ubuntu server with a free SSL certificate using Certbot. This complete 2026 step-by-step guide shows you how to install, configure, and verify Let’s Encrypt SSL on Ubuntu for a secure and SEO-friendly website.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/BijQbwjTnWoTLxmLPR9cIlnPh899I2A8qI0sexmw.png" alt="How to Install Free SSL on Ubuntu Server Using Certbot (Step-by-Step 2026 Guide)" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 class="ds-markdown-paragraph"><strong>Introduction</strong></h2>
<p class="ds-markdown-paragraph">In today's digital landscape, securing your website with HTTPS is no longer optional&mdash;it's a critical standard. An SSL certificate encrypts data between your server and your users, protects sensitive information, boosts your SEO ranking, and builds trust with visitors.</p>
<p class="ds-markdown-paragraph">Fortunately, you don't need to spend a fortune.&nbsp;<a title="Let's Encrypt official website" href="https://letsencrypt.org/" target="_blank" rel="noopener"><strong>Let's Encrypt</strong></a>&nbsp;provides free, automated, and open SSL certificates. The easiest way to use it on Ubuntu is with&nbsp;<strong>Certbot</strong>.</p>
<p class="ds-markdown-paragraph">This step-by-step 2026 guide will walk you through installing a free SSL certificate on your Ubuntu server using Certbot, for both Nginx and Apache web servers.</p>
<h2 data-start="952" data-end="971"><strong>Prerequisites</strong></h2>
<p data-start="973" data-end="1016">Before getting started, make sure you have:</p>
<ol data-start="1018" data-end="1275">
<li data-start="1018" data-end="1082">
<p data-start="1021" data-end="1082">&nbsp;A running <strong data-start="1033" data-end="1050">Ubuntu server</strong> (22.04 or later recommended).</p>
</li>
<li data-start="1083" data-end="1167">
<p data-start="1086" data-end="1167">&nbsp;A <strong data-start="1090" data-end="1105">domain name</strong> (e.g., <code data-start="1113" data-end="1126">example.com</code>) pointing to your server&rsquo;s IP address.</p>
</li>
<li data-start="1168" data-end="1228">
<p data-start="1171" data-end="1228"><strong data-start="1173" data-end="1192">Nginx or Apache</strong> web server installed and running.</p>
</li>
<li data-start="1229" data-end="1275">
<p data-start="1232" data-end="1275"><strong data-start="1234" data-end="1257">Root or sudo access</strong> to your server.</p>
</li>
<li data-start="1229" data-end="1275">Your <strong>domain's DNS</strong> pointing to your server's public IP address</li>
</ol>
<h2 data-start="1282" data-end="1321"><strong>Step 1: Update Your Ubuntu Server</strong></h2>
<p data-start="1323" data-end="1402">Start by updating your package list to ensure you&rsquo;re using the latest versions:</p>
<p data-start="1323" data-end="1402">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1323" data-end="1402">sudo apt update &amp;&amp; sudo apt upgrade -y</p>
<p data-start="1323" data-end="1402">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="1461" data-end="1490"><strong>Step 2: Install Certbot</strong></h2>
<p data-start="1492" data-end="1585">Certbot is the official client from Let&rsquo;s Encrypt used to obtain and manage SSL certificates.</p>
<h3 data-start="1587" data-end="1607">For Nginx users:</h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo apt install certbot python3-certbot-nginx -y</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3>For Apache users:</h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo apt install certbot python3-certbot-apache -y</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2194" data-end="2328">&nbsp;</p>
<h2 data-start="1762" data-end="1805"><strong>Step 3: Obtain a Free SSL Certificate</strong></h2>
<p>Now you&rsquo;ll issue a free SSL certificate for your domain.</p>
<h3><strong>For Nginx:</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo certbot --nginx -d <strong>yourdomain</strong>.com -d www.<strong>yourdomain</strong>.com</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h3><strong>For Apache:</strong></h3>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>&nbsp;sudo certbot --apache -d <strong>yourdomain</strong>.com -d www.<strong>yourdomain</strong>.com</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>you need to write your domain name in place of <strong>yourdoman&nbsp;</strong></p>
<p data-start="2045" data-end="2072"><strong>Certbot will automatically:</strong></p>
<ul data-start="2073" data-end="2192">
<li data-start="2073" data-end="2113">
<p data-start="2075" data-end="2113">Verify your domain via Let&rsquo;s Encrypt</p>
</li>
<li data-start="2114" data-end="2143">
<p data-start="2116" data-end="2143">Configure your web server</p>
</li>
<li data-start="2144" data-end="2160">
<p data-start="2146" data-end="2160">Enable HTTPS</p>
</li>
<li data-start="2161" data-end="2192">
<p data-start="2163" data-end="2192">Install the SSL certificate</p>
</li>
</ul>
<p data-start="2194" data-end="2328">You&rsquo;ll be asked for an email (for renewal alerts) and to agree to the Let&rsquo;s Encrypt terms.<br data-start="2284" data-end="2287">After success, you&rsquo;ll see a message like:</p>
<p data-start="2194" data-end="2328">Congratulations! Your certificate and chain have been saved at&nbsp;</p>
<p data-start="2194" data-end="2328"><strong><code data-start="2397" data-end="2449">/etc/letsencrypt/live/yourdomain.com/fullchain.pem</code></strong></p>
<h2 data-start="2456" data-end="2493"><strong>Step 4: Verify SSL Installation</strong></h2>
<p data-start="2495" data-end="2542">To verify that SSL is correctly installed, run:</p>
<p data-start="2495" data-end="2542">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2495" data-end="2542">sudo certbot certificates</p>
<p data-start="2495" data-end="2542">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2583" data-end="2664">This will display your certificate details, expiration date, and domain coverage.</p>
<p data-start="2666" data-end="2703">Then visit your website in a browser:</p>
<p data-start="2666" data-end="2703">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="2666" data-end="2703">https://yourdomain.com</p>
<p data-start="2666" data-end="2703">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2735" data-end="2804">You should see a <strong data-start="2752" data-end="2778">secure padlock 🔒 icon</strong>, meaning HTTPS is active.</p>
<p data-start="2806" data-end="2883">You can also test it using <a title="SSL Labs Test Tool" href="https://manamil.dev/../../../../tools/ssl-server-test">SSL Labs Test.</a></p>
<h2 data-start="2890" data-end="2931"><strong>Step 5: Auto-Renew SSL Certificates</strong></h2>
<p data-start="2933" data-end="3021">Let&rsquo;s Encrypt certificates expire every <strong data-start="2973" data-end="2984">90 days</strong>, but you can auto-renew them easily.</p>
<p data-start="3023" data-end="3067">Enable automatic renewal using this command:</p>
<p data-start="3023" data-end="3067">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="3023" data-end="3067">sudo systemctl enable certbot.timer</p>
<p data-start="3023" data-end="3067">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="3023" data-end="3067">To test renewal manually:</p>
<p data-start="3023" data-end="3067">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="3023" data-end="3067">sudo certbot renew --dry-run</p>
<p data-start="3023" data-end="3067">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="3023" data-end="3067">If you see <strong data-start="3196" data-end="3242">&ldquo;Congratulations, all renewals succeeded!&rdquo;</strong>, you&rsquo;re all set &mdash; your SSL will auto-renew every 60 days.</p>
<h2 data-start="4863" data-end="4919">FAQs &mdash; Free SSL Installation on Ubuntu with Certbot</h2>
<h3 data-start="4921" data-end="4944">1. What is Certbot?</h3>
<p data-start="4945" data-end="5077">Certbot is a free tool from the Electronic Frontier Foundation (EFF) used to install and manage SSL certificates from Let&rsquo;s Encrypt.</p>
<h3 data-start="5079" data-end="5119">2. Is Let&rsquo;s Encrypt SSL really free?</h3>
<p data-start="5120" data-end="5167">Yes &mdash; 100% free, trusted by all major browsers.</p>
<h3 data-start="5169" data-end="5227">3. How long does a Let&rsquo;s Encrypt SSL certificate last?</h3>
<p data-start="5228" data-end="5315">Each certificate is valid for <strong data-start="5258" data-end="5269">90 days</strong>, but Certbot can auto-renew it automatically.</p>
<h3 data-start="5317" data-end="5363">4. Can I use this for Laravel or PHP apps?</h3>
<p data-start="5364" data-end="5468">Absolutely! Laravel, PHP, or Node.js &mdash; any app running on your Ubuntu web server can use this SSL setup.</p>
<h3 data-start="5470" data-end="5511">5. What happens if SSL renewal fails?</h3>
<p data-start="5512" data-end="5592">You&rsquo;ll get an email alert from Let&rsquo;s Encrypt. You can also manually renew using:</p>
<p data-start="5512" data-end="5592">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="5512" data-end="5592">sudo certbot renew</p>
<p data-start="5512" data-end="5592">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="5625" data-end="5670">6. Can I install SSL on multiple domains?</h3>
<p data-start="5671" data-end="5711">Yes! Just add multiple <code data-start="5694" data-end="5698">-d</code> flags, like:</p>
<p data-start="5671" data-end="5711">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="5671" data-end="5711">sudo certbot --nginx -d example.com -d api.example.com</p>
<p data-start="5671" data-end="5711">&lt;/code&gt;&lt;/pre&gt;</p>
<h3 data-start="5780" data-end="5832">7. Does this method work on all Ubuntu versions?</h3>
<p data-start="5833" data-end="5924">Yes, but Ubuntu 22.04 LTS or later is highly recommended for better stability and security.</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/BijQbwjTnWoTLxmLPR9cIlnPh899I2A8qI0sexmw.png" type="image/png" length="1464253" />
        <media:content url="https://manamil.dev/storage/uploads/posts/BijQbwjTnWoTLxmLPR9cIlnPh899I2A8qI0sexmw.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Thu, 06 Nov 2025 07:51:10 +0000</pubDate>

      
                        <category><![CDATA[install free SSL Ubuntu]]></category>
                  <category><![CDATA[SSL Ubuntu server]]></category>
                  <category><![CDATA[Certbot Ubuntu guide]]></category>
                  <category><![CDATA[Let’s Encrypt SSL Ubuntu]]></category>
                  <category><![CDATA[free HTTPS Ubuntu]]></category>
                  <category><![CDATA[install Certbot Ubuntu]]></category>
                  <category><![CDATA[Ubuntu SSL certificate setup]]></category>
                  <category><![CDATA[secure website Ubuntu]]></category>
                  <category><![CDATA[Ubuntu Certbot tutorial]]></category>
                  <category><![CDATA[SSL for Laravel on Ubuntu]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Laravel Cloud vs Vapor — Which One Should You Choose in 2026?]]></title>
      <link>https://manamil.dev/blog/laravel/laravel-cloud-vs-vapor-which-one-should-you-choose-in-2026</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel-cloud-vs-vapor-which-one-should-you-choose-in-2026</guid>

      
      <description><![CDATA[
        <p>Laravel Cloud vs Vapor — explore the differences, features, and pricing to decide which Laravel hosting solution fits your project best in 2026</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/6UfGUKtTJah869aZQFhHIG8Lj3M2XU2uTSXgPshl.png" alt="Laravel Cloud vs Vapor — Which One Should You Choose in 2026?" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2 data-start="362" data-end="377">Introduction</h2>
<p data-start="379" data-end="599">When it comes to deploying Laravel applications, developers now have multiple modern options. Two of the most powerful are <strong data-start="502" data-end="519">Laravel Cloud</strong> and <strong data-start="524" data-end="541">Laravel Vapor</strong> &mdash; both created or maintained under the Laravel ecosystem.</p>
<p data-start="601" data-end="821">While they sound similar, Laravel Cloud and Laravel Vapor serve slightly different purposes. This post will help you understand what they are, how they work, and which one you should choose for your next Laravel project.</p>
<h2 class="_1vwisb34"><strong>What is Laravel Cloud?</strong></h2>
<p data-start="601" data-end="821"><span class="_1vwisb38" data-testid="youchat-text"><strong>Laravel Cloud</strong>&nbsp;is the newest official platform for deploying, managing, and scaling Laravel applications. Announced and launched by the Laravel team in 2024, Laravel Cloud aims to provide an all-in-one experience for developers who want to host their Laravel projects with minimal configuration. It offers a user-friendly dashboard, automated deployments, built-in CI/CD, and tight integration with the Laravel ecosystem.</span></p>
<p data-start="601" data-end="821"><span class="_1vwisb38" data-testid="youchat-text"><strong>Key Features:</strong></span></p>
<ul class="_1vwisb37">
<li class="f7g24p0" translate="no"><strong>Managed Hosting:</strong>&nbsp;Laravel Cloud handles server provisioning, security, and maintenance.</li>
<li class="f7g24p0" translate="no"><strong>Automatic Deployments:</strong>&nbsp;Push to Git and let Laravel Cloud handle the rest.</li>
<li class="f7g24p0" translate="no"><strong>Database &amp; Cache Services:</strong>&nbsp;Easily provision MySQL, Redis, and other services.</li>
<li class="f7g24p0" translate="no"><strong>Scalability:</strong>&nbsp;Scale your application with just a few clicks.</li>
<li class="f7g24p0" translate="no"><strong>Team Collaboration:</strong>&nbsp;Invite team members and manage permissions.</li>
<li class="f7g24p0" translate="no"><strong>Deep Laravel Integration:</strong> Built by the same team, ensuring best compatibility and support.</li>
</ul>
<p>Laravel Cloud is ideal for developers who want an <strong data-start="1530" data-end="1574">easy-to-use, all-in-one hosting solution</strong> for Laravel apps &mdash; without worrying about AWS, SSH, or Docker.</p>
<h2><strong>What is Laravel Vapor?</strong></h2>
<p><strong>Laravel Vapor</strong> lets you deploy Laravel apps without managing servers, using the power and flexibility of Amazon Web Services behind the scenes. Launched in 2019, Vapor enables developers to deploy Laravel applications without worrying about infrastructure. It leverages AWS Lambda to run your application serverlessly, meaning you only pay for the compute time your code actually uses.</p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Key Features:</strong></span></p>
<ul class="_1vwisb37">
<li class="f7g24p0" translate="no"><strong>Serverless Architecture:</strong>&nbsp;No servers to manage; your app runs on AWS Lambda.</li>
<li class="f7g24p0" translate="no"><strong>Automatic Scaling:</strong>&nbsp;Instantly scales to handle any amount of traffic.</li>
<li class="f7g24p0" translate="no"><strong>Managed Databases &amp; Queues:</strong>&nbsp;Easily connect to RDS, SQS, Redis, and more.</li>
<li class="f7g24p0" translate="no"><strong>Zero Downtime Deployments:</strong>&nbsp;Deploy new versions of your app without downtime.</li>
<li class="f7g24p0" translate="no"><strong>Environment Management:</strong>&nbsp;Create and manage multiple environments (staging, production).</li>
<li class="f7g24p0" translate="no"><strong>Integrated Queues, Caching, and Storage:</strong> Seamlessly works with AWS services.</li>
</ul>
<p>Laravel Vapor is perfect for large-scale apps that need <strong data-start="2386" data-end="2422">high scalability and performance</strong>, without worrying about server maintenance.</p>
<h2 class="_1vwisb34"><strong>Laravel Cloud vs Laravel Vapor: Feature Comparison</strong></h2>
<table style="width: 96.3056%; height: 407.312px; border-collapse: collapse; border-style: solid;" border="1">
<thead>
<tr style="height: 34.375px;">
<th style="width: 17.9112%;">Feature</th>
<th style="width: 39.1977%;"><strong>Laravel Cloud</strong></th>
<th style="width: 42.8911%;"><strong>Laravel Vapor</strong></th>
</tr>
</thead>
<tbody>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Hosting Type</strong></td>
<td style="width: 39.1977%;">Managed cloud hosting</td>
<td style="width: 42.8911%;">Serverless (AWS Lambda)</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Infrastructure</strong></td>
<td style="width: 39.1977%;">Managed by Laravel Cloud</td>
<td style="width: 42.8911%;">AWS (Lambda, S3, RDS, etc.)</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Ease of Setup</strong></td>
<td style="width: 39.1977%;">Very easy (few clicks)</td>
<td style="width: 42.8911%;">Moderate (AWS setup required)</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Scalability</strong></td>
<td style="width: 39.1977%;">Good, managed scaling</td>
<td style="width: 42.8911%;">Excellent, auto-scales infinitely</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Performance</strong></td>
<td style="width: 39.1977%;">Fast and stable</td>
<td style="width: 42.8911%;">Extremely fast, serverless</td>
</tr>
<tr style="height: 52.9688px;">
<td style="width: 17.9112%;"><strong>Pricing Model</strong></td>
<td style="width: 39.1977%;">Simple monthly plan</td>
<td style="width: 42.8911%;">Pay-as-you-go (based on AWS usage)</td>
</tr>
<tr>
<td style="width: 17.9112%;"><strong>File Storage<br></strong></td>
<td style="width: 39.1977%;">Local Disk or mounted storage</td>
<td style="width: 42.8911%;">S3 (Cloud storage)</td>
</tr>
<tr style="height: 52.9688px;">
<td style="width: 17.9112%;"><strong>Control Level</strong></td>
<td style="width: 39.1977%;">Moderate (Laravel handles infra)</td>
<td style="width: 42.8911%;">High (you configure AWS resources)</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Ideal For</strong></td>
<td style="width: 39.1977%;">Small to medium Laravel apps &nbsp;teams, simplicity</td>
<td style="width: 42.8911%;">High-traffic, spiky workloads, advanced AWS users</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Database/Cache<br></strong></td>
<td class="_1vwisb3e" style="width: 39.1977%;">Managed (MySQL, Redis, etc.)</td>
<td class="_1vwisb3e" style="width: 42.8911%;">&nbsp;AWS RDS, Redis, etc.</td>
</tr>
<tr style="height: 33.375px;">
<td style="width: 17.9112%;"><strong>Maintenance</strong></td>
<td style="width: 39.1977%;">Fully managed</td>
<td style="width: 42.8911%;">Minimal (but AWS knowledge helps)</td>
</tr>
</tbody>
</table>
<h2 data-start="3356" data-end="3410">Choosing Between Laravel Cloud and Laravel Vapor</h2>
<h3 data-start="3412" data-end="3444">Choose <strong data-start="3423" data-end="3440">Laravel Cloud</strong> if:</h3>
<ul data-start="3445" data-end="3658">
<li data-start="3445" data-end="3505">
<p data-start="3447" data-end="3505">You want a simple, Laravel-friendly deployment solution.</p>
</li>
<li data-start="3506" data-end="3567">
<p data-start="3508" data-end="3567">You don&rsquo;t want to deal with AWS or server configurations.</p>
</li>
<li data-start="3568" data-end="3616">
<p data-start="3570" data-end="3616">You run a small or medium-sized application.</p>
</li>
<li class="f7g24p0" translate="no">Your team prefers using an all-in-one dashboard for deployments, scaling, and management.</li>
<li data-start="3617" data-end="3658">
<p data-start="3619" data-end="3658">You prefer predictable monthly billing.</p>
</li>
</ul>
<h3 data-start="3660" data-end="3692">Choose <strong data-start="3671" data-end="3688">Laravel Vapor</strong> if:</h3>
<ul data-start="3693" data-end="3901">
<li data-start="3693" data-end="3743">
<p data-start="3695" data-end="3743">You want ultimate scalability and flexibility.</p>
</li>
<li data-start="3744" data-end="3793">
<p data-start="3746" data-end="3793">Your app experiences large spikes in traffic.</p>
</li>
<li data-start="3794" data-end="3850">
<p data-start="3796" data-end="3850">You&rsquo;re comfortable with AWS (or have a DevOps team).</p>
</li>
<li data-start="3851" data-end="3901">
<p data-start="3853" data-end="3901">You want a fully serverless, event-driven setup.</p>
</li>
</ul>
<h3><strong>Setup Overview</strong></h3>
<h3 data-start="4358" data-end="4386">Setting Up Laravel Cloud</h3>
<ol data-start="4387" data-end="4603">
<li data-start="4387" data-end="4449">
<p data-start="4390" data-end="4449">Sign up at <a class="decorated-link" href="https://cloud.laravel.com" target="_new" rel="noopener" data-start="4401" data-end="4447">cloud.laravel.com</a></p>
</li>
<li data-start="4450" data-end="4485">
<p data-start="4453" data-end="4485">Connect your GitHub repository</p>
</li>
<li data-start="4486" data-end="4527">
<p data-start="4489" data-end="4527">Configure your environment variables</p>
</li>
<li data-start="4528" data-end="4564">
<p data-start="4531" data-end="4564">Choose your database and region</p>
</li>
<li data-start="4565" data-end="4603">
<p data-start="4568" data-end="4603">Deploy your app with one click</p>
</li>
</ol>
<h3 data-start="4605" data-end="4633"><strong>Setting Up Laravel Vapor</strong></h3>
<ol data-start="4634" data-end="4988">
<li data-start="4634" data-end="4696">
<p data-start="4637" data-end="4696">Sign up at <a class="decorated-link" href="https://vapor.laravel.com" target="_new" rel="noopener" data-start="4648" data-end="4694">vapor.laravel.com</a></p>
</li>
<li data-start="4697" data-end="4800">
<p data-start="4700" data-end="4737">Install the Vapor CLI via Composer:</p>
</li>
</ol>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>composer global require laravel/vapor-cli</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>&nbsp; &nbsp; &nbsp;3. Authenticate your account:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>vapor login</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>&nbsp; &nbsp; 4.&nbsp; Link your project:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>vapor init</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>&nbsp; &nbsp; 5. Deploy your app:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>vapor deploy production</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>Your Laravel app will now be live on AWS Lambda!</p>
<h2 data-start="5046" data-end="5072"><strong>Pros and Cons Both of them</strong></h2>
<h3 data-start="5074" data-end="5091"><strong>Laravel Cloud</strong></h3>
<p data-start="5092" data-end="5101"><strong data-start="5092" data-end="5101">Pros:</strong></p>
<ul data-start="5102" data-end="5211">
<li data-start="5102" data-end="5122">
<p data-start="5104" data-end="5122">Super easy setup</p>
</li>
<li data-start="5123" data-end="5149">
<p data-start="5125" data-end="5149">Managed infrastructure</p>
</li>
<li data-start="5150" data-end="5177">
<p data-start="5152" data-end="5177">No AWS knowledge needed</p>
</li>
<li data-start="5178" data-end="5211">
<p data-start="5180" data-end="5211">Great UI and monitoring tools</p>
</li>
</ul>
<p data-start="5213" data-end="5222"><strong data-start="5213" data-end="5222">Cons:</strong></p>
<ul data-start="5223" data-end="5273">
<li data-start="5223" data-end="5244">
<p data-start="5225" data-end="5244">Less customizable</p>
</li>
<li data-start="5245" data-end="5273">
<p data-start="5247" data-end="5273">Not as scalable as Vapor</p>
</li>
</ul>
<h3 data-start="5275" data-end="5292"><strong>Laravel Vapor</strong></h3>
<p data-start="5293" data-end="5302"><strong data-start="5293" data-end="5302">Pros:</strong></p>
<ul data-start="5303" data-end="5429">
<li data-start="5303" data-end="5336">
<p data-start="5305" data-end="5336">Fully serverless and scalable</p>
</li>
<li data-start="5337" data-end="5355">
<p data-start="5339" data-end="5355">Uses AWS power</p>
</li>
<li data-start="5356" data-end="5391">
<p data-start="5358" data-end="5391">Great for enterprise-level apps</p>
</li>
<li data-start="5392" data-end="5429">
<p data-start="5394" data-end="5429">Auto scaling and minimal downtime</p>
</li>
</ul>
<p data-start="5431" data-end="5440"><strong data-start="5431" data-end="5440">Cons:</strong></p>
<ul data-start="5441" data-end="5505">
<li data-start="5441" data-end="5470">
<p data-start="5443" data-end="5470">AWS costs can get complex</p>
</li>
<li data-start="5471" data-end="5505">
<p data-start="5473" data-end="5505">Slightly higher learning curve</p>
</li>
</ul>
<h2 class="_1vwisb34"><strong>FAQs: Laravel Cloud vs Laravel Vapor</strong></h2>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q1: Can I use both Laravel Cloud and Vapor on the same app?</strong><br>A: No, you typically choose one platform per environment. Each manages deployments differently and is designed to be used independently.</span></p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q2: Which platform is more beginner-friendly?</strong><br>A:&nbsp;<strong>Laravel Cloud</strong>&nbsp;is generally easier for beginners, as it abstracts away much of the infrastructure complexity. Vapor is powerful but assumes some AWS familiarity.</span></p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q3: Is there a big price difference?</strong><br>A:&nbsp;<strong>Laravel Cloud</strong>&nbsp;has straightforward pricing based on resources.&nbsp;<strong>Vapor</strong>&nbsp;requires a subscription and AWS usage fees, which can be unpredictable for high-traffic or resource-heavy apps.</span></p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q4: Can I migrate from Vapor to Cloud (or vice versa) later?</strong><br>A: Migration is possible but may require code or configuration changes, especially around storage, caching, and queue systems.</span></p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q5: Does Laravel Cloud support serverless?</strong><br>A: Laravel Cloud uses managed servers, not a serverless architecture. If you specifically need serverless, go with Vapor.</span></p>
<p><span class="_1vwisb38" data-testid="youchat-text"><strong>Q6: What about custom domains, SSL, and environment variables?</strong><br>A: Both platforms support custom domains, free SSL certificates, and easy management of environment variables.</span></p>
<p><strong><span class="_1vwisb38" data-testid="youchat-text">Q7: How to install Laravel?</span></strong></p>
<p>A: Before deploying your <strong>Laravel application</strong>, you must properly install and configure the <strong>Laravel</strong> <strong>Nginx setup.</strong> For step-by-step instructions, check out our detailed guide: <span style="text-decoration: underline;"><a title="Laravel Installation on Ubuntu with Nginx &ndash; Complete Configuration Guide" href="https://manamil.dev/../../../../blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide">Laravel Nginx Setup Guide.</a></span></p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/6UfGUKtTJah869aZQFhHIG8Lj3M2XU2uTSXgPshl.png" type="image/png" length="1360799" />
        <media:content url="https://manamil.dev/storage/uploads/posts/6UfGUKtTJah869aZQFhHIG8Lj3M2XU2uTSXgPshl.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Wed, 05 Nov 2025 11:41:19 +0000</pubDate>

      
                        <category><![CDATA[laravel cloud]]></category>
                  <category><![CDATA[laravel vapor]]></category>
                  <category><![CDATA[laravel cloud vs vapor]]></category>
                  <category><![CDATA[laravel vapor comparison]]></category>
                  <category><![CDATA[laravel hosting]]></category>
                  <category><![CDATA[laravel serverless]]></category>
                  <category><![CDATA[vapor vs cloud]]></category>
                  <category><![CDATA[laravel cloud pricing]]></category>
                  <category><![CDATA[laravel vapor features]]></category>
                  <category><![CDATA[laravel cloud tutorial]]></category>
                  <category><![CDATA[laravel vapor guide]]></category>
                  </item>
      
    <item>
      <title><![CDATA[How to Install Composer for Ubuntu and Windows Step-by-Step Guide]]></title>
      <link>https://manamil.dev/blog/laravel/how-to-install-composer-for-ubuntu-and-windows-step-by-step-guide</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/how-to-install-composer-for-ubuntu-and-windows-step-by-step-guide</guid>

      
      <description><![CDATA[
        <p>In this post you can learn how to install Composer on both Windows and Ubuntu step by step. The complete setup guide covers everything from downloading Composer to verifying installation — perfect for beginners and developers in 2025.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/stY4w5mklJ7sgS2VQYRPaf7feYdSZqldE6B0Hwyb.png" alt="How to Install Composer for Ubuntu and Windows Step-by-Step Guide" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <p data-start="239" data-end="452">When it comes to building <strong data-start="265" data-end="321">powerful and scalable web applications using Laravel</strong>, the first step is setting up <strong data-start="352" data-end="364">Composer</strong> &mdash; a PHP dependency manager that installs and manages all the libraries <a title="Laravel Installation on Ubuntu with Nginx &ndash; Complete Configuration Guide" href="https://manamil.dev/../../../../blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide"><span style="text-decoration: underline;"><strong>Laravel</strong></span></a> needs.</p>
<p data-start="454" data-end="649">Without Composer, you cannot install Laravel or manage its ecosystem efficiently. That&rsquo;s why understanding how to <strong data-start="568" data-end="611">install and configure Composer properly</strong> is essential for every PHP developer.</p>
<p data-start="651" data-end="814">In this complete guide, you will learn how to install Composer on both <strong data-start="722" data-end="733">Windows</strong> and <strong data-start="738" data-end="748">Ubuntu</strong>, step by step, so you can start your Laravel projects smoothly.</p>
<h2 data-start="651" data-end="814"><strong>Why Composer is Important</strong></h2>
<p data-start="851" data-end="1027">Composer is a <strong data-start="865" data-end="903">dependency management tool for PHP</strong>. It allows you to declare the libraries your project requires and then manages (installs and updates) them automatically.</p>
<p data-start="1029" data-end="1061">For Laravel, Composer handles:</p>
<ul data-start="1063" data-end="1184">
<li data-start="1063" data-end="1106">
<p data-start="1065" data-end="1106"><a title="Laravel Installation on Ubuntu with Nginx &ndash; Complete Configuration Guide" href="https://manamil.dev/../../../../blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide">Installing Laravel and its dependencies</a></p>
</li>
<li data-start="1107" data-end="1140">
<p data-start="1109" data-end="1140">Managing packages and plugins</p>
</li>
<li data-start="1141" data-end="1184">
<p data-start="1143" data-end="1184">Keeping your PHP environment consistent</p>
</li>
</ul>
<p data-start="1186" data-end="1285">Think of Composer as the <strong data-start="1211" data-end="1228">&ldquo;npm for PHP&rdquo;</strong> &mdash; it makes managing PHP projects simple and efficient.</p>
<h2 data-start="1287" data-end="1329"><strong>Composer Use in Popular PHP Frameworks</strong></h2>
<p data-start="1331" data-end="1398">Composer is used in almost every modern PHP framework, including:</p>
<ul data-start="1400" data-end="1536">
<li data-start="1400" data-end="1411">
<p data-start="1402" data-end="1411">Symfony</p>
</li>
<li data-start="1412" data-end="1423">
<p data-start="1414" data-end="1423">Laravel</p>
</li>
<li data-start="1424" data-end="1441">
<p data-start="1426" data-end="1441">CodeIgniter 4</p>
</li>
<li data-start="1442" data-end="1453">
<p data-start="1444" data-end="1453">CakePHP</p>
</li>
<li data-start="1454" data-end="1462">
<p data-start="1456" data-end="1462">Yii2</p>
</li>
<li data-start="1463" data-end="1481">
<p data-start="1465" data-end="1481">Slim Framework</p>
</li>
<li data-start="1482" data-end="1493">
<p data-start="1484" data-end="1493">FuelPHP</p>
</li>
<li data-start="1494" data-end="1536">
<p data-start="1496" data-end="1536">OctoberCMS, Drupal, Magento, WordPress</p>
</li>
</ul>
<h2 data-start="1567" data-end="1637"><strong>System Requirements</strong></h2>
<p data-start="1567" data-end="1637">To install Composer, make sure your system meets these requirements:</p>
<ul data-start="1639" data-end="1777">
<li data-start="1639" data-end="1703">
<p data-start="1641" data-end="1703"><strong data-start="1641" data-end="1657">PHP version:</strong> 8.3 or above (older versions may also work)</p>
</li>
<li data-start="1704" data-end="1777">
<p data-start="1706" data-end="1777"><strong data-start="1706" data-end="1723">Local server:</strong> Latest version of XAMPP or WAMP (for Windows users)</p>
</li>
</ul>
<h2 data-start="1784" data-end="1817">Installing Composer on Windows</h2>
<p data-start="1819" data-end="1899">Follow these steps to install Composer on <strong data-start="1861" data-end="1872">Windows</strong> for Laravel development.</p>
<h2 data-start="1901" data-end="1935">Step 1: Check PHP Installation</h2>
<p data-start="1937" data-end="2007">Composer requires PHP to run. Open your <strong data-start="1977" data-end="1995">Command Prompt</strong> and type:</p>
<p data-start="1937" data-end="2007">&lt;pre&gt;&lt;code&gt;php -v&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1937" data-end="2007">If PHP is installed, you will see a version number similar to this:</p>
<p data-start="1937" data-end="2007"><img src="https://manamil.dev/../../../../storage/gallery/img/JlK3tjCcJ8qreipbDXyZmanamil-dev.png" alt="" width="602" height="301"></p>
<h2 data-start="1937" data-end="2007"><strong>Step 2: Download Composer Installer</strong></h2>
<p data-start="2161" data-end="2272">Go to the official Composer website:<br data-start="2197" data-end="2200"><a class="decorated-link" href="https://getcomposer.org/download/" target="_blank" rel="noopener" data-start="2200" data-end="2270">https://getcomposer.org/download/</a></p>
<p data-start="2274" data-end="2342">Click on <strong data-start="2283" data-end="2307">&ldquo;Composer-Setup.exe&rdquo;</strong> (Windows Installer) to download.</p>
<h2 data-start="2274" data-end="2342">Step 3: Run the Composer Installer</h2>
<ul>
<li data-start="2389" data-end="2423">
<p data-start="2391" data-end="2423">Run the downloaded <code data-start="2410" data-end="2416">.exe</code> file</p>
</li>
<li data-start="2424" data-end="2514">
<p data-start="2426" data-end="2514">The installer will automatically detect your PHP installation and configure everything</p>
</li>
<li data-start="2515" data-end="2569">
<p data-start="2517" data-end="2569">Proceed with the <strong data-start="2534" data-end="2567">default installation settings</strong></p>
</li>
<li data-start="2570" data-end="2621">
<p data-start="2572" data-end="2621">Once installation is complete, click <strong data-start="2609" data-end="2619">Finish</strong></p>
</li>
</ul>
<h2 data-start="2628" data-end="2659"><strong>Step 4: Verify Installation</strong></h2>
<p data-start="2661" data-end="2698">Open Command Prompt again and type:</p>
<p data-start="2661" data-end="2698">&lt;pre&gt;&lt;code&gt;composer&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2661" data-end="2698">If you see the Composer version and usage details, installation was successful.</p>
<p data-start="2661" data-end="2698"><img src="https://manamil.dev/../../../../storage/gallery/img/thxWJHK0RvYKt25gKFezmanamil-dev.png" width="697" height="372"></p>
<h2 data-start="2825" data-end="2859"><strong>Step 5: Check Composer Version</strong></h2>
<p>Test your installation by typing:</p>
<p>&lt;pre&gt;&lt;code&gt;composer -v&lt;/code&gt;&lt;/pre&gt;</p>
<p>You should see output like:</p>
<p>picture</p>
<h2><strong>Installing Composer on Ubuntu (Linux)&nbsp;</strong></h2>
<p data-start="3068" data-end="3123">Follow these steps to install Composer on <strong data-start="3110" data-end="3120">Ubuntu</strong>.</p>
<p><span style="text-decoration: underline;"><em><span style="font-size: 10pt;"><a title="Laravel Installation on Ubuntu with Nginx &ndash; Complete Configuration Guide" href="https://manamil.dev/../../../../blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide">(If you want to install laravel on ubuntu.)</a></span></em></span></p>
<h2 data-start="3125" data-end="3155">Step 1: Update Your System</h2>
<p data-start="3157" data-end="3194">First, update your system packages:</p>
<p data-start="3157" data-end="3194">&lt;pre&gt;&lt;code&gt;sudo apt update<br>sudo apt upgrade -y&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="3250" data-end="3297">Step 2: Install PHP and Required Extensions</h2>
<p data-start="3299" data-end="3363">Composer requires PHP and some extensions. Install them using:</p>
<p data-start="2861" data-end="2896">&lt;pre&gt;&lt;code&gt;sudo apt install php php-cli unzip curl -y&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2861" data-end="2896">Verify PHP installation:</p>
<p data-start="2861" data-end="2896">&lt;pre&gt;&lt;code&gt;php -v&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2861" data-end="2896">If you see the php version and usage details, installation was successful.</p>
<p data-start="2861" data-end="2896"><img src="https://manamil.dev/../../../../storage/gallery/img/Vb494phahh1CMibt6Oivmanamil-dev.png" alt=""></p>
<h2 data-start="3489" data-end="3528">Step 3: Download Composer Installer</h2>
<p data-start="3530" data-end="3559">Run the following commands:</p>
<p data-start="3530" data-end="3559">&lt;pre&gt;&lt;code&gt;cd ~<br>curl -sS https://getcomposer.org/installer -o composer-setup.php<br>&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="3644" data-end="3689">Verify Installer Signature (Recommended)</h2>
<p>&lt;pre&gt;&lt;code&gt;HASH_EXPECTED="$(curl -sS https://composer.github.io/installer.sig)"<br>php -r "if (hash_file('sha384', 'composer-setup.php') === trim('$HASH_EXPECTED')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"<br>&lt;/code&gt;&lt;/pre&gt;</p>
<p>If you see <strong data-start="3977" data-end="3999">Installer verified</strong>, you can continue.<br data-start="4018" data-end="4021">If you see <strong data-start="4032" data-end="4053">Installer corrupt</strong>, delete the file and re-download.</p>
<h2 data-start="4096" data-end="4133">Step 4: Install Composer Globally</h2>
<p>&lt;pre&gt;&lt;code&gt;sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer&lt;/code&gt;&lt;/pre&gt;</p>
<p>Remove the installer (temporary file):</p>
<p>&lt;pre&gt;&lt;code&gt;rm composer-setup.php&lt;/code&gt;&lt;/pre&gt;</p>
<p><strong data-start="4302" data-end="4320">Why remove it?</strong><br data-start="4320" data-end="4323">The <code data-start="4327" data-end="4347">composer-setup.php</code> file is only a temporary installer script. Once Composer is installed, it is no longer needed.</p>
<h2 data-start="4451" data-end="4482">Step 5: Verify Installation</h2>
<p data-start="4484" data-end="4533">Check Composer version to confirm installation:</p>
<p data-start="4484" data-end="4533">&lt;pre&gt;&lt;code&gt;composer -V&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1054" data-end="1112">You should see something like:</p>
<p data-start="1054" data-end="1112"><em>&lt;code&gt;</em></p>
<p data-start="1054" data-end="1112"><em>&nbsp; &nbsp;______<br>&nbsp; / ____/___ &nbsp;____ ___ &nbsp;____ &nbsp;____ &nbsp;________ &nbsp;_____<br>&nbsp;/ / &nbsp; / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/<br>/ /___/ /_/ / / / / / / /_/ / /_/ (__ &nbsp;) &nbsp;__/ /<br>\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/_/<br><br>Composer version 2.8.11 2025-08-21 11:29:39<br>&lt;/code&gt;</em></p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/stY4w5mklJ7sgS2VQYRPaf7feYdSZqldE6B0Hwyb.png" type="image/png" length="548569" />
        <media:content url="https://manamil.dev/storage/uploads/posts/stY4w5mklJ7sgS2VQYRPaf7feYdSZqldE6B0Hwyb.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Tue, 04 Nov 2025 09:27:15 +0000</pubDate>

      
                        <category><![CDATA[composer installation]]></category>
                  <category><![CDATA[php composer install]]></category>
                  <category><![CDATA[composer installation guide]]></category>
                  <category><![CDATA[how to install composer step by step]]></category>
                  <category><![CDATA[php composer install windows]]></category>
                  <category><![CDATA[php composer ubuntu]]></category>
                  </item>
      
    <item>
      <title><![CDATA[Laravel Installation on Ubuntu with Nginx – Complete Configuration Guide]]></title>
      <link>https://manamil.dev/blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide</link>
      <guid isPermaLink="true">https://manamil.dev/blog/laravel/laravel-installation-on-ubuntu-with-nginx-complete-configuration-guide</guid>

      
      <description><![CDATA[
        <p>Learn how to install Laravel on Ubuntu with Nginx. Step-by-step configuration guide to set up a robust PHP framework environment.</p>
                  <p><img src="https://manamil.dev/storage/uploads/posts/LYinurEmBk80kn4FdDAEWvl7uxw4GfMwixYpjxtm.png" alt="Laravel Installation on Ubuntu with Nginx – Complete Configuration Guide" width="600" /></p>
              ]]></description>

      
      <content:encoded><![CDATA[
        <h2><strong>Intorduction</strong></h2>
<p><a title="Laravel" href="https://laravel.com" target="_blank" rel="noopener"><strong>Laravel</strong></a> is the ultimate <strong>free and open-source PHP framework</strong> designed for building <strong>fast, secure, and reliable web applications</strong>. It has quickly become the <strong>industry standard</strong> thanks to its powerful, cohesive toolset that guarantees a <strong>streamlined development process</strong> for any modern PHP project.</p>
<p>In this guide, we&rsquo;ll learn in detail <strong data-start="172" data-end="223">how to install Laravel on any version of Ubuntu</strong> and <strong data-start="228" data-end="255">configure it with <a title="Nginx" href="https://nginx.org" target="_blank" rel="noopener">Nginx</a></strong> for <strong data-start="260" data-end="284">the best performance</strong>. Whether you&rsquo;re a <strong data-start="303" data-end="315">beginner</strong> or an <strong data-start="322" data-end="347">experienced developer</strong>, this tutorial is <strong data-start="366" data-end="417">perfect for learning the complete Laravel setup</strong>.</p>
<h2><strong>Installing Nginx on Ubuntu.</strong></h2>
<p>Before deploying your application, the <strong>Laravel Nginx configuration</strong> must be properly installed and set up. As one of the <strong>fastest and most reliable web servers for PHP applications</strong>, correctly configuring <strong>Nginx</strong> is a critical step for maximizing your <strong>Laravel</strong> site's <strong>performance and security</strong>.</p>
<h2><strong>Step 1: Update System Packages</strong></h2>
<p>First, make sure your system is up-to-date by running:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo apt update &amp;&amp; sudo apt upgrade -y</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>This ensures that all existing packages are updated before installing new ones.</p>
<h2><strong>Step 2: Install Nginx</strong></h2>
<p>Now install <strong data-start="566" data-end="575">Nginx</strong> using the following command:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo apt install nginx -y</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>After installation, enable Nginx to start automatically on boot:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo systemctl enable nginx<br>sudo systemctl start nginx</p>
<p>&lt;/pre&gt;&lt;/code&gt;</p>
<h2 data-start="780" data-end="813"><strong>Step 3: Verify Installation</strong></h2>
<p data-start="814" data-end="873">To check if Nginx is installed and running properly, run:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo systemctl status nginx</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p>or open your browser and visit:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>http://localhost</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="973" data-end="1078">You should see the <strong data-start="992" data-end="1015">&ldquo;Welcome to Nginx!&rdquo;</strong> page &mdash; this means Nginx is successfully installed and running.</p>
<p data-start="973" data-end="1078"><img src="https://manamil.dev/../../../../storage/uploads/posts/ou66xG07xuYJezLseeiK5OkGOrtoXbllOFhK7rTG.png" alt="Welcome to Nginx!" width="1920" height="1080"></p>
<h2><strong>Next Step: Install PHP 8.3 and Essential Extensions for Laravel</strong></h2>
<p>With <strong>Nginx successfully installed</strong>, the critical next step is to set up <strong>PHP</strong>. This powerful server-side language is the backbone required to efficiently run your <strong>Laravel</strong> application.</p>
<p>We will install the <a href="https://www.php.net"><strong>latest stable version, PHP 8.3</strong>,</a> ensuring you get the best performance, security, and compatibility. Crucially, we'll include <strong>all necessary PHP extensions</strong> to guarantee your Laravel project functions flawlessly right out of the box.</p>
<h2><strong>Step 1: Add PHP Repository</strong></h2>
<p data-start="553" data-end="658">First, add the official PHP repository maintained by Ondřej Sur&yacute;, which provides the latest PHP packages:</p>
<p>&lt;pre&gt;&lt;code&gt;</p>
<p>sudo add-apt-repository ppa:ondrej/php -y<br>sudo apt update</p>
<p>&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="730" data-end="779"><strong>Step 2: Install PHP and Required Extensions</strong></h2>
<p data-start="780" data-end="858">Next, install PHP 8.3 along with the commonly required extensions for Laravel:</p>
<p data-start="780" data-end="858">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="780" data-end="858">sudo apt install php8.3 php8.3-fpm php8.3-cli php8.3-common php8.3-mysql php8.3-xml php8.3-mbstring php8.3-curl php8.3-zip php8.3-bcmath php8.3-gd unzip -y</p>
<p data-start="780" data-end="858">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="780" data-end="858">&nbsp;</p>
<h2 data-start="1028" data-end="1065"><strong>Step 3: Verify PHP Installation</strong></h2>
<p data-start="1066" data-end="1133">After installation, check if PHP is installed correctly by running:</p>
<p data-start="1066" data-end="1133">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="1066" data-end="1133">php -v</p>
<p data-start="1066" data-end="1133">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="1066" data-end="1133"><img role="presentation" src="https://manamil.dev/../../../../storage/uploads/posts/T6frdp7uCP3kpRXwgWh4zFjCVWBB6EHIh0aqr28Y.png" alt="" width="1918" height="1079"></p>
<p data-start="1066" data-end="1133">You should see something like:</p>
<p data-start="1066" data-end="1133"><em>&lt;code&gt;</em></p>
<p data-start="1066" data-end="1133"><em>PHP 8.3.6 (cli) (built: Jul 14 2025 18:30:55) (NTS)</em><br><em>Copyright (c) The PHP Group</em><br><em>Zend Engine v4.3.6, Copyright (c) Zend Technologies</em><br><em>&nbsp; &nbsp; with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies</em></p>
<p data-start="1066" data-end="1133"><em>&lt;/code&gt;</em></p>
<h2 data-start="1222" data-end="1258"><strong>Step 4: Enable PHP-FPM Service</strong></h2>
<p data-start="1259" data-end="1341">Since Nginx uses PHP-FPM to process PHP files, make sure it&rsquo;s enabled and running:</p>
<p data-start="780" data-end="858">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="780" data-end="858">sudo systemctl enable php8.3-fpm<br>sudo systemctl start php8.3-fpm</p>
<p data-start="780" data-end="858">&lt;/code&gt;&lt;/pre&gt;</p>
<h2><strong>Installing Composer - <span style="text-decoration: underline;"><a title="How to Install Composer for Ubuntu and Windows Step-by-Step Guide" href="https://manamil.dev/../../../../blog/laravel/how-to-install-composer-for-ubuntu-and-windows-step-by-step-guide">Step-by-Step Guide for Ubuntu and Windows</a></span></strong></h2>
<p data-start="207" data-end="430"><a title="Composer" href="https://getcomposer.org/doc/00-intro.md" target="_blank" rel="noopener"><strong data-start="207" data-end="219">Composer</strong></a> is a powerful dependency manager for PHP. It&rsquo;s used to install and manage all Laravel packages and libraries efficiently.<br data-start="341" data-end="344">Without Composer, you can&rsquo;t create or run a Laravel project &mdash; so let&rsquo;s install it now.</p>
<h2 data-start="432" data-end="473"><strong>Step 1: Download Composer Installer</strong></h2>
<p data-start="474" data-end="535">Run the following command to download the Composer installer:</p>
<p data-start="474" data-end="535">&lt;pre&gt;&lt;/code&gt;</p>
<p data-start="474" data-end="535">php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"</p>
<p data-start="474" data-end="535">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="623" data-end="684"><strong>Step 2: Verify the Installer (Optional but Recommended)</strong></h2>
<p data-start="685" data-end="757">To ensure the installer file is safe, you can verify its integrity with:</p>
<p data-start="474" data-end="535">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="474" data-end="535">HASH="$(wget -q -O - https://composer.github.io/installer.sig)"&nbsp;<br>php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"</p>
<p data-start="474" data-end="535">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="474" data-end="535">&nbsp;</p>
<h2 data-start="1014" data-end="1053"><strong>Step 3: Install Composer Globally</strong></h2>
<p data-start="1054" data-end="1112">Now run the command below to install Composer system-wide:</p>
<p data-start="474" data-end="535">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="474" data-end="535">sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer</p>
<p data-start="474" data-end="535">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="474" data-end="535">&nbsp;</p>
<h2 data-start="1203" data-end="1236"><strong>Step 4: Verify Installation</strong></h2>
<p data-start="1237" data-end="1282">Once installed, check if Composer is working:</p>
<p data-start="474" data-end="535">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="474" data-end="535">composer -V</p>
<p data-start="474" data-end="535">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="474" data-end="535"><img role="presentation" src="https://manamil.dev/../../../../storage/uploads/posts/s09wNaWN67LDEwimaJTgjAQmAUCu1dcrS4butBmA.png" alt="" width="1920" height="1080"></p>
<p data-start="1054" data-end="1112">You should see something like:</p>
<p data-start="1054" data-end="1112"><em>&lt;code&gt;</em></p>
<p data-start="1054" data-end="1112"><em>&nbsp; &nbsp; ______<br>&nbsp; / ____/___ &nbsp;____ ___ &nbsp;____ &nbsp;____ &nbsp;________ &nbsp;_____<br>&nbsp;/ / &nbsp; / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/<br>/ /___/ /_/ / / / / / / /_/ / /_/ (__ &nbsp;) &nbsp;__/ /<br>\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /_/<br>Composer version 2.8.11 2025-08-21 11:29:39<br>&lt;/code&gt;</em></p>
<p data-start="1054" data-end="1112">&nbsp;</p>
<h2 data-start="243" data-end="300"><strong>Installing Laravel and Configuring Nginx for Localhost.</strong></h2>
<p data-start="302" data-end="464">Now that <strong data-start="311" data-end="320">Nginx</strong>, <strong data-start="322" data-end="329">PHP</strong>, and <strong data-start="335" data-end="347">Composer</strong> are ready, let&rsquo;s install <strong data-start="373" data-end="384">Laravel</strong> and configure Nginx to run it locally on your system &lt;code&gt;(e.g. <code data-start="444" data-end="462">http://localhost</code>).&lt;/code&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<h2 data-start="302" data-end="464">Step 1: Create a New Laravel Project</h2>
<p data-start="513" data-end="596">Run the following command to create a new Laravel project inside the web directory:</p>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs">&nbsp;</div>
</div>
</div>
</div>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">cd /var/www/<br>sudo composer create-project --prefer-dist laravel/laravel myproject</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<p data-start="302" data-end="464">After installation, move into the project folder:</p>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">cd myproject</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<h2 data-start="302" data-end="464"><br><strong>Step 2: Set Folder Permissions</strong></h2>
<p>Laravel needs write access for <code data-start="841" data-end="850">storage</code> and <code data-start="855" data-end="872">bootstrap/cache</code> folders.<br data-start="881" data-end="884">Run the following commands:</p>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">sudo chown -R www-data:www-data /var/www/myproject<br>sudo chmod -R 775 /var/www/myproject/storage<br>sudo chmod -R 775 /var/www/myproject/bootstrap/cache</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<h2 data-start="302" data-end="464"><strong>Step 3: Configure Nginx for Laravel (Localhost)</strong></h2>
<p data-start="1132" data-end="1198">Now create a new Nginx configuration file for the Laravel project:</p>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">sudo nano /etc/nginx/sites-available/laravel</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<p data-start="302" data-end="464">Paste this configuration (optimized for localhost):</p>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p>server {<br>&nbsp; &nbsp; listen 80;<br>&nbsp; &nbsp; server_name localhost;<br>&nbsp; &nbsp; root /var/www/myproject/public;</p>
<p>&nbsp; &nbsp; index index.php index.html;</p>
<p>&nbsp; &nbsp; location / {<br>&nbsp; &nbsp; &nbsp; &nbsp; try_files $uri $uri/ /index.php?$query_string;<br>&nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; location ~ \.php$ {<br>&nbsp; &nbsp; &nbsp; &nbsp; include snippets/fastcgi-php.conf;<br>&nbsp; &nbsp; &nbsp; &nbsp; fastcgi_pass unix:/run/php/php8.3-fpm.sock;<br>&nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; location ~ /\.ht {<br>&nbsp; &nbsp; &nbsp; &nbsp; deny all;<br>&nbsp; &nbsp; }<br>}</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<h2 data-start="1704" data-end="1739"><strong>Step 4: Enable and Reload Nginx</strong></h2>
<p data-start="1741" data-end="1809">Enable this configuration by creating a symlink and reloading Nginx:</p>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/<br>sudo nginx -t<br>sudo systemctl reload nginx</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="302" data-end="464">&nbsp;</p>
<h2 data-start="1943" data-end="1980"><strong>Step 5: Access Laravel in Browser</strong></h2>
<p data-start="1982" data-end="2014">Now open your browser and visit:</p>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs">&nbsp;</div>
</div>
</div>
</div>
<p data-start="302" data-end="464">&lt;pre&gt;&lt;code&gt;</p>
<p data-start="302" data-end="464">http://localhost</p>
<p data-start="302" data-end="464">&lt;/code&gt;&lt;/pre&gt;</p>
<p data-start="2042" data-end="2122">If everything is configured properly, you&rsquo;ll see the <strong data-start="2095" data-end="2119">Laravel welcome page</strong> 🎉</p>
<p data-start="302" data-end="464">&nbsp;</p>
      ]]></content:encoded>

      
              <enclosure url="https://manamil.dev/storage/uploads/posts/LYinurEmBk80kn4FdDAEWvl7uxw4GfMwixYpjxtm.png" type="image/png" length="903502" />
        <media:content url="https://manamil.dev/storage/uploads/posts/LYinurEmBk80kn4FdDAEWvl7uxw4GfMwixYpjxtm.png" medium="image" />
      
      
      <author>muhammadmanamil@gmail.com (Muhammad Manamil)</author>

      
      <pubDate>Mon, 03 Nov 2025 13:33:32 +0000</pubDate>

      
                        <category><![CDATA[Laravel]]></category>
                  <category><![CDATA[Nginx]]></category>
                  <category><![CDATA[Ubuntu]]></category>
                  <category><![CDATA[Laravel Nginx installation]]></category>
                  <category><![CDATA[server configuration]]></category>
                  <category><![CDATA[PHP-FPM]]></category>
                  <category><![CDATA[virtual host]]></category>
                  <category><![CDATA[deploy Laravel]]></category>
                  <category><![CDATA[Ubuntu 22.04 Laravel]]></category>
                  </item>
  
</channel>
</rss>
