The first beta of Inertia.js v3 is now available. This release replaces Axios with a built-in XHR client, introduces a Vite plugin that handles page resolution and SSR automatically, and adds first-class support for optimistic updates, standalone HTTP requests, and layout props. Less boilerplate, fewer dependencies, and a bunch of new capabilities that make your Inertia apps feel faster.
We're releasing v3 as a beta so the Community can test it, report issues, and help us ship a rock-solid stable release. Install it today and let us know what you think.
Already on v2? The upgrade guide covers all breaking changes and migration steps.
What's New in Inertia v3?
Here's everything we shipped in the first beta version of the new Inertia.js.
The Vite Plugin
Setting up an Inertia app in v2 required a resolve callback to map page names to components, a setup callback to mount the app, and a separate SSR entry point with its own configuration. That boilerplate was nearly identical across projects, so we figured: why not handle it for you?
The new @inertiajs/vite plugin handles it. Add the plugin to your Vite config and call createInertiaApp() with no arguments:
1// vite.config.js 2import inertia from '@inertiajs/vite' 3import laravel from 'laravel-vite-plugin' 4import { defineConfig } from 'vite' 5 6export default defineConfig({ 7 plugins: [ 8 laravel({ 9 input: ['resources/css/app.css', 'resources/js/app.js'],10 refresh: true,11 }),12 inertia(),13 ],14})
1// resources/js/app.js2import { createInertiaApp } from '@inertiajs/vue3'3 4createInertiaApp()
That's your entire entry point. The plugin resolves pages from your ./Pages directory, handles lazy-loading and code splitting, and wires up SSR. The setup and resolve callbacks are now optional. You may still provide them for custom behavior, and a pages shorthand lets you point to a different directory.
SSR in Development, Without a Separate Server
In v2, running SSR during development meant building the SSR bundle and starting a separate Node.js process. With the Vite plugin, SSR works automatically during development. Run npm run dev, and your pages are server-rendered.
The production workflow is unchanged: build with vite build && vite build --ssr and start the SSR server with php artisan inertia:start-ssr.
Error reporting during SSR has also been overhauled. When a component fails to render on the server, Inertia now logs the component name, URL, and actionable hints. You may disable SSR on specific routes via middleware or the facade, and a SsrRenderFailed event is dispatched for monitoring.
Axios Removed
Inertia no longer ships with or depends on Axios. The built-in XHR client handles all internal HTTP communication, resulting in a smaller bundle with fewer dependencies. The qs package has been removed as well. An Axios adapter is also available for those who prefer to keep using it.
Standalone HTTP Requests
Not every request in an Inertia app should trigger a page visit. API calls, search endpoints, and external service requests don't need Inertia's full page lifecycle. Previously, developers reached for Axios or fetch for these, losing the reactive state management that useForm provides.
The new useHttp hook gives you that same useForm developer experience, but for plain HTTP requests:
1<script setup> 2import { useHttp } from '@inertiajs/vue3' 3 4const http = useHttp({ 5 query: '', 6}) 7 8function search() { 9 http.get('/api/search', {10 onSuccess: (response) => {11 console.log(response)12 },13 })14}15</script>16 17<template>18 <input v-model="http.query" @input="search" />19 <div v-if="http.processing">Searching...</div>20</template>
It has reactive state, error handling, file upload progress, and request cancellation. It also supports optimistic updates and precognition.
Optimistic Updates
When a user clicks a like button or toggles a bookmark, they shouldn't have to wait for the server to see the result.
Chain the optimistic() method before any router visit. The callback receives the current page props and returns the values to apply immediately:
1router.optimistic((props) => ({2 post: {3 ...props.post,4 likes: props.post.likes + 1,5 },6})).post(`/posts/${post.id}/like`)
The update is applied instantly. When the server responds, the real data takes over. If the request fails, props revert to their original state automatically. Multiple optimistic updates in flight are tracked independently, so concurrent requests don't interfere with each other.
Optimistic updates work with router visits, the <Form> component, useForm, and useHttp.
Instant Visits
Instant visits let Inertia swap to the target page component immediately while the server request fires in the background. The user sees the new page right away with shared props, and the full page data merges in when the response arrives:
1<Link href="/dashboard" component="Dashboard">Dashboard</Link>
The target component renders immediately with shared data. Page-specific props arrive when the server responds. The navigation feels instant, even though a full server request still happens behind the scenes.
Layout Props
Persistent layouts survive navigation, which is one of Inertia's most powerful features. The new useLayoutProps hook lets layouts declare defaults that pages may override, eliminating the need for event buses or provide/inject patterns:
1<!-- Layout.vue -->2<script setup>3import { useLayoutProps } from '@inertiajs/vue3'4const { title, showSidebar } = useLayoutProps({5 title: 'My App',6 showSidebar: true,7})8</script>
Pages update these values with setLayoutProps(). Named layouts, nested layouts, and static props are all supported.
Exception Handling
Exceptions like 404s may occur outside the Inertia middleware (the request never reaches your routes), so the error response doesn't have access to shared data or the root view. This was one of those things that required workarounds in v2.
The new handleExceptionsUsing() method gives you full control:
1use Inertia\Inertia; 2use Inertia\ExceptionResponse; 3 4Inertia::handleExceptionsUsing(function (ExceptionResponse $response) { 5 if (in_array($response->statusCode(), [403, 404, 500, 503])) { 6 return $response->render('ErrorPage', [ 7 'status' => $response->statusCode(), 8 ])->withSharedData(); 9 }10});
Calling withSharedData() explicitly resolves the Inertia middleware and includes your shared props in the error page. Returning null falls through to Laravel's default exception rendering.
Everything Else About Inertia v3
This release includes a number of additional improvements:
- Nested prop types.
Inertia::optional(),Inertia::defer(), andInertia::merge()now work inside nested arrays, with dot-notation support for partial reloads. - Event renames.
invalidandexceptionare nowhttpExceptionandnetworkError, with new per-visitonHttpExceptionandonNetworkErrorcallbacks. - Default layout. Set a default layout in
createInertiaAppinstead of defining it on every page. - Form component generics. TypeScript generics for type-safe errors and slot props.
- Enum support. Use PHP enums directly in
Inertia::render()responses. - ESM only. All packages now ship as ES Modules. CommonJS
require()imports are no longer supported. preserveErrorsoption. Preserve validation errors during partial reloads.
Breaking Changes
Inertia v3 requires PHP 8.2+, Laravel 11+, React 19+ (React adapter), and Svelte 5+ (Svelte adapter).
Other breaking changes to be aware of:
- Axios is no longer included. Migrate interceptors to the built-in HTTP client or use the Axios adapter.
qspackage is no longer bundled. Install it directly if your app imports it.Inertia::lazy(), deprecated in v2, has been removed. UseInertia::optional()instead.router.cancel()is nowrouter.cancelAll()with granular control over which request types to cancel.futureoptions are removed. All v2 future flags are now always enabled.- Config file structure has changed. Republish with
php artisan vendor:publish --provider="Inertia\\ServiceProvider" --force.
The full upgrade guide covers every change in detail.