Starting from laravel new, here is every command and
file change needed to end up with this stack.
Laravel is the backend — routing, database, business logic.
composer create-project laravel/laravel example-app
cd example-app
Lets controllers return React pages directly, no separate JSON API needed. The
inertia:middleware command
generates app/Http/Middleware/HandleInertiaRequests.php.
composer require inertiajs/inertia-laravel
php artisan inertia:middleware
In bootstrap/app.php, append it to the
web middleware group:
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
App\Http\Middleware\HandleInertiaRequests::class,
]);
})
React (UI), Inertia's React adapter + Vite plugin, and Tailwind v4:
npm install @inertiajs/react react react-dom
npm install -D @inertiajs/vite @vitejs/plugin-react
npm install -D tailwindcss @tailwindcss/vite
vite.config.jsimport laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import inertia from '@inertiajs/vite';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.jsx'],
refresh: true,
}),
tailwindcss(),
inertia(),
react(),
],
});
Tailwind v4 needs no tailwind.config.js —
just import it in resources/css/app.css:
@import 'tailwindcss';
Delete Laravel's default resources/js/app.js
and create resources/js/app.jsx instead:
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} />);
},
});
resources/views/app.blade.php —
this is the one HTML page React mounts into:
<html>
<head>
@vite('resources/js/app.jsx')
@inertiaHead
</head>
<body>
@inertia
</body>
</html>
Instead of view(...), controllers/routes return
Inertia::render(...), and matching
.jsx files live under
resources/js/Pages/:
Route::get('/login', function () {
return Inertia::render('Auth/Login');
});
composer run dev
# or separately:
php artisan serve
npm run dev