inertiajs/inertia-laravel
Laravel adapter for Inertia.js: build single-page apps using classic server-side routing and controllers. Provides middleware, helpers, and response macros to render Inertia pages, share props, handle versioning, and integrate seamlessly with Laravel.
Installation:
composer require inertiajs/inertia-laravel
npm install @inertiajs/inertia @inertiajs/inertia-laravel
Run migrations:
php artisan inertia:middleware
Configure app/Http/Kernel.php:
Add Inertia middleware to $middlewareGroups['web']:
\Inertia\Middleware::class,
First Route/Controller:
Route::get('/dashboard', function () {
return Inertia::render('Dashboard', [
'users' => User::all(),
]);
});
Create Vue/React Component:
<!-- resources/js/Pages/Dashboard.vue -->
<template>
<div>
<h1>Dashboard</h1>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
users: Array,
},
};
</script>
Build Assets:
npm run dev
// resources/js/Pages/Posts/Index.vue
export default {
props: {
posts: Array,
errors: Object,
},
};
// routes/web.php
Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', [PostController::class, 'store']);
// app/Http/Controllers/PostController.php
public function index() {
return Inertia::render('Posts/Index', [
'posts' => Post::latest()->get(),
]);
}
public function store(Request $request) {
$validated = $request->validate([
'title' => 'required|string|max:255',
]);
Post::create($validated);
return redirect()->route('posts.index');
}
return Inertia::render('PageName', ['prop' => $value]);
public function share(Request $request): array
{
return [
'auth' => [
'user' => $request->user(),
],
'settings' => [
'theme' => 'dark',
],
];
}
return Inertia::render('Page', [
'users' => User::all(),
'deferred' => fn() => [
'stats' => Stats::calculate(),
],
]);
<script setup>
const { data: stats } = await useFetch('/api/stats');
</script>
return Inertia::render('FormPage', [
'errors' => $validator->errors(),
]);
return redirect()->route('dashboard')->with([
'message' => 'Post created!',
]);
return redirect()->route('posts.index');
<Link href="/posts">Posts</Link>
Inertia::disableSsr();
return Inertia::render('NonSSRPage');
config(['inertia.ssr.runtime' => 'edge']);
return Inertia::render('Dashboard', [
'user' => Auth::user(),
]);
if (Gate::denies('view-post', $post)) {
abort(403);
}
event(new PostCreated($post));
return Inertia::render('Posts/Index', ['posts' => Post::latest()->get()]);
$response = $this->get('/dashboard');
$response->assertInertia(fn (AssertableInertia $page) => $page
->component('Dashboard')
->has('users', 3)
);
$response->assertInertia(fn (AssertableInertia $page) =>
$page->loadDeferredProps(fn (AssertableInertia $page) =>
$page->has('stats', ['visitors' => 100])
)
);
return Inertia::render('Page', [
'users' => User::all()->toArray(),
'posts' => Post::all()->only(['id', 'title']),
]);
return Inertia::render('Page', [
'once' => fn() => ['data' => 'persists'],
]);
<script setup>
const { data: component } = await useAsyncComponent(() =>
import(`./Components/${dynamicComponent}.vue`)
);
</script>
// app/Providers/InertiaServiceProvider.php
public function share(Request $request): array
{
return [
'app' => [
'name' => config('app.name'),
],
];
}
Middleware Priority:
Authenticate but before VerifyCsrfToken in $middlewareGroups['web'].app/Http/Kernel.php.Deferred Props Caching:
rescue to handle failures:
'deferred' => fn() => [
'stats' => Stats::calculate()->rescue(fn() => null),
],
Flash Data Loss:
Inertia::location() or Inertia::redirect().with() or session()->flash().SSR Mismatches:
npm run dev or npm run build after changes.Prop Type Mismatches:
null and false).Middleware Conflicts:
TrimStrings) may interfere with Inertia's request handling.if (! request()->expectsJson()).Testing Quirks:
assertInertia() requires exact component names (case-sensitive).->component('Exact/Case/Name').Log Props:
\Log::info('Inertia props:', [
'page' => Inertia::current()->page,
'props' => Inertia::current()->props,
]);
Check SSR Health:
php artisan inertia:check-ssr
NODE_ENV=production and assets are built.Inspect Deferred Props:
$deferred = Inertia::current()->deferred;
\Log::debug('Deferred props:', $deferred);
Hydration Errors:
Middleware Debugging:
// app/Http/Kernel.php
protected $middleware = [
// \App\Http\Middleware\TrimStrings::class, // Disable temporarily
];
Custom Prop Modifiers:
// app/Providers/InertiaServiceProvider.php
public function modifyProps($props, $page)
{
if ($page === 'Dashboard') {
$props['formattedDate'] = now()->format('Y-m-d');
}
return $props;
}
**
How can I help you explore Laravel packages today?