In a recent project, I wanted to keep my Laravel Blade setup super lightweight — no Vue, no React, no heavy front-end frameworks.
But I still wanted smooth page transitions like a real SPA, without full-page reloads every time users clicked a link.

So, I decided to build a simple AJAX page loader that:

  • Loads only the page content inside the
    tag.
  • Updates the URL without reloading the browser.
  • Shows a loading spinner while fetching.
  • Supports browser back and forward buttons!

The result?
✔Lightning-fast page loads.
✔Smooth user experience.
✔Very little JavaScript code.

Let’s dive into how I built it!

Step 1: Write a Small JavaScript

In my app.js, I added a simple AJAX fetch system.

resources/js/app.js

document.addEventListener('DOMContentLoaded', () => {
    const mainElement = document.querySelector('main');

    function showLoader() {
        mainElement.innerHTML = `
            
                
            
        `;
    }

    function loadPage(url, push = true) {
        showLoader();

        fetch(url, {
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        })
        .then(response => response.text())
        .then(html => {
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');

            const newContent = doc.querySelector('main')?.innerHTML;
            if (newContent) {
                mainElement.innerHTML = newContent;
                if (push) {
                    history.pushState(null, '', url);
                }
            }
        })
        .catch(err => {
            console.error('Page load failed', err);
            mainElement.innerHTML = `Page failed to load.`;
        });
    }

    document.body.addEventListener('click', e => {
        const link = e.target.closest('a[data-link]');
        if (link) {
            e.preventDefault();
            const url = link.getAttribute('href');
            loadPage(url);
        }
    });

    window.addEventListener('popstate', () => {
        loadPage(location.pathname, false);
    });
});

Step 2: Update Blade Links

Every link you want to load via AJAX should have the data-link attribute:

href="/dashboard" data-link>Dashboard
 href="/profile" data-link>Profile
 href="/settings" data-link>Settings

When users click, the page content will update instantly inside

, without a full browser reload!

Step 3: (Optional) Improve UX with a Spinner Loader

Before fetching a page, I display a simple CSS spinner using Tailwind CSS:

class="flex justify-center items-center h-40">
     class="animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500">

This gives users feedback that something is happening — no more "dead time" during slow network requests.

Final Result

✔Fast, smooth page loads.
✔Real URL updates (so users can bookmark/share pages).
✔Browser Back and Forward buttons work correctly.
✔Tiny JavaScript — no extra libraries needed!
✔Laravel Blade templates still do all the heavy lifting

All with just plain Laravel, Blade, and a little JavaScript!

If you're building a Laravel app and don't want the complexity of a full frontend framework, I highly recommend trying this out!

Feel free to copy or improve this idea!