Laravel 12 combined with Inertia.js 2 and React offers a powerful way to build modern single-page applications without the complexity of a traditional API. This setup delivers the speed of React with the simplicity and SEO benefits of server-side routing.
💡 This approach is ideal if you want SPA-like UX while keeping Laravel routing, controllers, and middleware intact.
Why Use Laravel with Inertia.js and React?
Inertia.js acts as a bridge between Laravel and React, allowing you to build JavaScript-powered interfaces without abandoning server-side architecture.
-
No REST or GraphQL APIs required
-
Server-side routing with client-side rendering
-
Better SEO compared to client-only SPAs
-
Shared validation, authentication, and middleware
Inertia Server-Side Setup in Laravel 12
Create a Fresh Laravel Project
composer create-project laravel/laravel inertia-react-app
cd inertia-react-app
Install Inertia Laravel Adapter
composer require inertiajs/inertia-laravel
Create Inertia Middleware
php artisan inertia:middleware
This command generates the HandleInertiaRequests middleware, which shares data between Laravel and React.
Register Middleware in Laravel 12
use App\Http\Middleware\HandleInertiaRequests;
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
HandleInertiaRequests::class,
]);
})
⚠️ Without registering this middleware, Inertia responses will not work correctly.
Root Blade Template for Inertia
Inertia requires a single root Blade file that loads your React application.
<!-- resources/views/app.blade.php -->
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@viteReactRefresh
@vite('resources/js/app.jsx')
@inertiaHead
</head>
<body>
@inertia
</body>
</html>
The @viteReactRefresh directive enables hot reload for React components during development.
Basic Inertia Route Example
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Home');
});
This route renders a React component named Home without returning JSON or views manually.
Client-Side Setup with React and Vite
Install Required NPM Packages
npm install @inertiajs/react
npm install @vitejs/plugin-react
Configure Inertia App Entry
// resources/js/app.jsx
import { createInertiaApp } from '@inertiajs/react'
import { createRoot } from 'react-dom/client'
createInertiaApp({
resolve: name => {
const pages = import.meta.glob('./Pages/**/*.jsx', { eager: true })
return pages[`./Pages/${name}.jsx`]
},
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />)
},
})
This configuration dynamically resolves all React pages and mounts the app using React 18.
Create Your First React Page
// resources/js/Pages/Home.jsx
const Home = () => {
return (
<div>Home</div>
)
}
export default Home
Once this file exists, visiting / will automatically render it through Inertia.
Using a Custom Inertia Root Element
You can mount Inertia on a custom DOM ID instead of the default.
@inertia('custom-app-id')
Set Custom Root View
Inertia::setRootView('app');
💡 Useful when integrating Inertia inside an existing Laravel layout or CMS.
Vite Configuration File
Update your vite.config.js file with the following configuration. This setup supports React, Tailwind CSS, and Inertia-driven hot reloading.
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
tailwindcss(),
react(),
],
server: {
watch: {
ignored: ['**/storage/framework/views/**'],
},
},
});
Final Thoughts
Laravel 12 with Inertia.js 2 and React provides a clean, scalable, and SEO-friendly way to build modern web applications. You avoid API overhead while still enjoying a fully reactive frontend experience.
This architecture is ideal for dashboards, admin panels, SaaS products, and content-driven platforms that demand performance and maintainability.