jati / ashravel
Zero-JS Single Page Application (SPA) functionality for Laravel Blade.
Requires
- php: ^8.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
- illuminate/view: ^9.0|^10.0|^11.0|^12.0
README
TurboBlade is an ultra-lightweight, zero-JS package for Laravel that turns your classic Server-Side Rendered (Blade) application into a blazingly fast Single Page Application (SPA).
Stop writing Webpack configs. Stop fighting React/Vue reactivity. Stop worrying about Livewire network bloat. Just write plain PHP/HTML, and let TurboBlade handle the magic.
๐ก๏ธ Security Analysis (Scraping & Injection)
Before deploying TurboBlade, it's essential to understand its security posture:
1. Cross-Site Scripting (XSS) Injection
Are you safe? YES, provided you follow Laravel standards.
TurboBlade updates your page using document.body.innerHTML and explicitly re-evaluates <script> tags found in the new HTML.
- The Rule: You MUST use Laravel's default
{{ $variable }}syntax to output user-generated content. This automatically escapes HTML entities. - The Danger: If you use the raw syntax
{!! $variable !!}to output user input, an attacker can inject malicious<script>tags. TurboBlade will execute them upon page morph. Treat your Blade templates with the exact same XSS precautions as a standard Laravel app.
2. Web Scraping & SEO (Search Engine Optimization)
Is it safe from scrapers? NO. Is it good for SEO? YES. TurboBlade is built on the HTML-over-the-wire philosophy. Your Laravel backend still returns fully rendered HTML on every request.
- Scrapers: Malicious bots and scrapers do not execute JavaScript. They just read the HTTP response. Because TurboBlade uses standard HTML routing, scrapers can read your content easily. To protect against malicious scraping, you must use server-side rate limiting (
ThrottleRequestsmiddleware) or a WAF like Cloudflare. - SEO: This architecture is the "Holy Grail" for SEO. Googlebot will see your website as a traditional, fully-rendered HTML site, giving you a perfect 100/100 Lighthouse SEO score, while real humans experience the site as a lightning-fast SPA.
๐ฅ๏ธ Server Requirements & Compatibility
Ashravel is designed to be highly compatible with both modern and legacy enterprise applications. Because the core magic happens in Vanilla JavaScript, the PHP footprint is extremely minimal.
Supported Versions:
- PHP:
8.0,8.1,8.2,8.3 - Laravel:
9.x,10.x,11.x
(Note: We intentionally drop support for PHP 7.x and Laravel 8 to encourage modern security standards, even though the code technically could run on them).
๐ฆ Installation
Install the package via Composer (we recommend pinning to a major version):
composer require jati/ashravel:"^1.0"
Publish the JavaScript assets to your public directory:
php artisan vendor:publish --tag="turboblade-assets"
๐ How to Use (Usage Guide)
1. Global Setup
Open your main layout file (usually resources/views/layouts/app.blade.php), and place the Blade directive just before the closing </head> or </body> tag:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Awesome Laravel App</title> <!-- Inject TurboBlade Engine --> @turbobladeScripts </head> <body> <nav> <a href="/home">Home</a> <a href="/about">About Us</a> </nav> <main> @yield('content') </main> </body> </html>
2. The Magic
You don't need to do anything else!
The moment you add @turbobladeScripts, all <a> links and <form> submissions across your entire application will automatically be intercepted. The browser will no longer do a full hard reload. Instead, TurboBlade fetches the next page in the background, merges the <head> (to update CSRF tokens and CSS), and morphs the <body> instantly.
3. Ignoring Specific Links/Forms
If you have a link that you do not want TurboBlade to intercept (for example, a file download, a payment gateway redirect, or a heavy PDF generation), simply add the data-turbo-ignore attribute to the HTML element:
<!-- This link will cause a normal, full-page browser reload --> <a href="/download-invoice/123" data-turbo-ignore>Download PDF</a> <!-- This form will bypass TurboBlade completely --> <form action="/checkout" method="POST" data-turbo-ignore> @csrf <button type="submit">Pay Now</button> </form>
4. Integration with Third-Party JS (Alpine.js, Google Maps, etc.)
Because TurboBlade swaps the DOM, third-party JavaScript libraries might lose their state or event listeners. TurboBlade dispatches a custom event turboblade:load every time a page navigation finishes.
You can listen to this event to re-initialize your plugins:
document.addEventListener('turboblade:load', function(event) { console.log("New page loaded at: " + event.detail.url); // Example: Re-initialize Alpine.js components if (typeof Alpine !== 'undefined') { Alpine.initTree(document.body); } });
โ ๏ธ SPA Architectural Gotchas (Must Read)
Because TurboBlade transforms your traditional app into a Single Page Application, the browser never actually performs a hard refresh. Please be aware of these two common SPA pitfalls:
1. Memory Leaks (Global Event Listeners)
If you attach an event listener to window or document inside a specific page (e.g., welcome.blade.php), it will not be destroyed when the user navigates away. If the user visits that page 10 times, the listener will be attached 10 times, causing a memory leak.
Solution: Always bind page-specific listeners to local DOM elements (which get destroyed by TurboBlade during navigation), OR explicitly remove global listeners, OR initialize them once in your main layout.
2. External Scripts in the Body
TurboBlade safely re-evaluates inline scripts (e.g., <script>alert('hi')</script>) when navigating. However, it will ignore external scripts (e.g., <script src="https://stripe.com/v3/"></script>) if they are placed inside the <body>.
Solution: Always place external <script src="..."> tags inside the <head> of your layout. TurboBlade's smart asset merger will detect and load them perfectly.
๐ก๏ธ Server-Side HTTP Middleware & Redirect Support
To handle SPA HTTP 301/302 Redirects and force hard browser reloads from your controllers, register the optional TurboBladeMiddleware:
1. Registering the Middleware
In bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php (Laravel 10 and below):
->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ \Ashravel\TurboBlade\Middleware\TurboBladeMiddleware::class, ]); })
- SPA Redirect Support: When a frontend SPA request (
X-TurboBlade: true) encounters a backend redirect, the middleware attaches anX-TurboBlade-Locationheader so JavaScript can accurately updatehistory.pushState.
2. Forcing a Hard Browser Reload
When you need to force a full hard page reload (e.g., after login, logout, or session reset), use the static helper in your Controller:
use Ashravel\TurboBlade\Middleware\TurboBladeMiddleware; public function logout(Request $request) { Auth::logout(); $response = redirect('/login'); return TurboBladeMiddleware::forceReload($response); }
๐งช Testing & Verification
Ashravel includes an automated test suite using PHPUnit 10 and Orchestra Testbench 9.
To run the verification suite locally:
# 1. Install development dependencies composer install # 2. Run the test suite composer test # or vendor/bin/phpunit
The test suite validates:
- Blade Directive: Compilation and rendering of
@turbobladeScripts. - Asset Publishing: Execution of
artisan vendor:publish --tag="turboblade-assets". - HTTP Middleware: SPA redirect location headers (
X-TurboBlade-Location) and reload instructions (X-TurboBlade-Reload).
๐จโ๐ป Author
Rafly A.R ๐ง Email: raflypriyantoro@gmail.com ๐ธ Instagram: @galaxy_scream
๐ง Core Features Summary
- Zero-Config: 1 line of code to turn your app into an SPA.
- CSRF Safe: Automatically updates Laravel's
@csrftokens in the background on every navigation. - Scroll Memory: Remembers your exact scroll position when you press the browser's "Back" button.
- Asset Merging: Automatically downloads new
<link>CSS files if the new page requires them. - Redirect & Reload Aware: Full server-side middleware support for HTTP 302 redirects and forced reloads.