Category: Web Development

  • How to Change the public Folder to public_html in Laravel (Step-by-Step Guide)

    If you are deploying Laravel on shared hosting like Hostinger or cPanel servers, you may notice that the document root is public_html instead of Laravel’s default public directory. This mismatch can cause asset loading issues, broken storage links, or security concerns if not handled correctly.

    In this expert Laravel tutorial, you will learn how to change the Laravel public folder to public_html safely, including support for Vite, storage symlinks, and Hot Module Replacement (HMR).


    Why Change Laravel’s Public Folder to public_html?

    Many hosting providers enforce public_html as the web root. Common reasons to change it include:

    • Compatibility with cPanel / shared hosting
    • Avoiding unnecessary symlinks
    • Improved application security
    • Cleaner project structure
    • Proper Vite asset resolution

    ✅ This method works for Laravel 9, Laravel 10, and newer versions


    Prerequisites

    Before proceeding, ensure you have:

    • Laravel 9+
    • PHP 8 or higher
    • Node.js (for Vite)
    • Access to project files (SSH or FTP)

    Step 1: Override the Public Path in AppServiceProvider

    Laravel internally resolves the public directory using the service container. We override it to point to public_html.

    📍 File: app/Providers/AppServiceProvider.php

    
    
    
    
    
    /**
     * Overwrite public folder.
     */
    $this->app->bind('path.public', function () {
        return base_path('public_html');
    });
    

    Why This Is Important

    • Updates public_path() globally
    • Ensures asset helpers reference public_html
    • Prevents broken file paths in production

    Step 2: Configure the Public Path in bootstrap/app.php

    Modern Laravel versions define the public path during application bootstrapping.

    📍 File: bootstrap/app.php

    
    
    
    
    
    <?php
    
    use Illuminate\Foundation\Application;
    use Illuminate\Foundation\Configuration\Exceptions;
    use Illuminate\Foundation\Configuration\Middleware;
    
    $app = Application::configure(basePath: dirname(__DIR__))
        ->withRouting(
            web: __DIR__.'/../routes/web.php',
            commands: __DIR__.'/../routes/console.php',
            health: '/up',
        )
        ->withMiddleware(function (Middleware $middleware) {
            $middleware->validateCsrfTokens(except: [
                '/admin/upload',
            ]);
        })
        ->withExceptions(function (Exceptions $exceptions) {
            //
        })
        ->registered(function ($app) {
            $app->usePublicPath(
                path: realpath(base_path('/../public_html'))
            );
        })
        ->create();
    
    $app->bind('path.public', function () {
        return base_path().'/public_html';
    });
    
    return $app;
    

    SEO Benefit

    Ensures:

    • Proper asset loading
    • No broken CSS or JS files
    • Faster page rendering (Core Web Vitals)

    Step 3: Fix Storage Symlinks (storage:link)

    Laravel’s file uploads rely on the public directory. Update the symlink configuration accordingly.

    📍 File: config/filesystems.php

    
    
    
    
    
    'links' => [
        app()->basePath('public_html/storage') => storage_path('app/public'),
    ],
    

    Then run:

    
    
    
    
    
    php artisan storage:link
    

    Result

    Uploads will now be accessible at:

    
    
    
    
    
    /public_html/storage
    

    Step 4: Update Vite Configuration for public_html

    Vite must be aware of the new public directory for Hot Module Replacement (HMR) and production builds.

    📍 File: vite.config.js

    
    
    
    
    
    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    
    export default defineConfig({
        plugins: [
            laravel({
                input: ['resources/js/app.js'],
                publicDirectory: 'public_html',
            }),
        ],
        build: {
            outDir: 'public_html/build',
        },
        server: {
            hmr: {
                host: 'localhost',
            },
        },
    });
    

    Why This Matters for SEO

    • Prevents broken assets
    • Improves Lighthouse performance scores
    • Ensures proper asset versioning

    Step 5: Rename the Public Folder

    Rename Laravel’s default public directory:

    
    
    
    
    
    mv public public_html
    

    Make sure your server document root points to:

    
    
    
    
    
    /your-project/public_html
    

    Clear Cache and Rebuild Assets

    After all changes, run:

    
    
    
    
    
    php artisan optimize:clear
    npm run build
    

    This ensures:

    • Fresh configuration
    • Clean route & view caches
    • Correct asset compilation

    Common Issues and Fixes

    ProblemSolution
    Assets not loadingRebuild Vite assets
    Storage files 404Re-run storage:link
    HMR not workingSet correct HMR host
    Cached pathsRun optimize:clear

    Final Thoughts

    Changing Laravel’s public folder to public_html is 100% safe and production-ready when configured properly. This setup is ideal for:

    • Shared hosting
    • cPanel environments
    • Secure Laravel deployments

    By updating Laravel’s service container, bootstrap configuration, filesystem links, and Vite settings, you ensure long-term stability and SEO-friendly asset delivery.