Inertia X is a drop-in replacement for the Inertia client-side adapter with additional features. Currently only available for Svelte 5.
The <Frame>
component lets you embed one Inertia page inside another Inertia page, each with its own navigation. This is useful for modals, wizards, sidebars, and more. You can find an example modal implementation using Frames here.
<script>
import { Frame } from 'inertiax-svelte'
</script>
<Frame src="/users/1/edit">
Loading...
</Frame>
The <Frame>
component accepts these props:
Prop | Default | Description |
---|---|---|
name |
random | The frame's name. Use this to target the frame directly in responses. The top-level frame is always named _top . |
src |
null | The URL of the page to load. If not provided, no request is made and the initial component and page are shown. |
renderLayout |
true if name == _top |
Whether to render the component's layout. |
initialComponent |
null | The component to show before making the request. Can be a promise. |
initialPage |
null | The initial Inertia page object with initial props. Gets replaced after the request completes. |
onclick |
noop | An event handler that runs before the frame's own click handler. Call preventDefault on the event to skip the frame's default handler. |
Any other props are passed down to the page component.
If you don't set initialComponent
, the child content shows until the request finishes. Use this to display loading spinners and animations.
When you make a request from inside a frame, the referer
header still contains the current window location.
The new X-Inertia-Frame-Src
header solves this. The Inertia router sets this header to the originating frame's URL. Use this header instead of referer
when you want to redirect users back to the previous URL.
On the backend, you can get the originating frame's name from the X-Inertia-Frame
header. The default top frame name is _top
.
For all frames except _top
, the preserveUrl
and replace
router visit options now default to true
.
By default, navigation through links, router.visit
calls, and form.submit
calls render their response in the same frame that made the request.
To render a response in a different frame, you have several options:
- Use the new
frame
router visit option:router.visit('/url', {frame: 'otherFrame'})
. - Set an
X-Inertia-Frame
response header with the target frame's name. - Add a
data-target="frame"
attribute to youra
tag.
You can also access a frame's router directly from the component:
<script>
function goSomewhereElse() {
frame.router.visit(...)
}
</script>
<Frame name="modal" bind:this={frame} />
or get it globally:
import { getRouter } from 'inertiax-svelte'
getRouter("modal").post("/users")
Inertia X lets you add custom callbacks to its navigation stack using the new pushExternal()
function. When you call this function, it adds the callbacks to the "stack" and calls the arrive()
function. When users navigate back with the browser's back button, the recede()
function gets called. Future forward/back navigation will call arrive()
and recede()
as users move back and forth. Inertia's normal navigation handling stops during these states.
<script>
import { history } from 'inertiax-core'
function onclick() {
history.pushExternal(url, {
arrive() {
alert("You arrived at an external history state")
},
recede() {
alert("You navigated back from an external history state")
}
})
}
</script>
<button {onclick}>Push external state</button>
Each frame component now has its own click handler. Clicks on elements with an href
attribute get handled automatically. To disable this, add the data-inertia-ignore
attribute to the element or any parent element. To disable globally, add data-inertia-ignore
to the body element.
You can still use the inertia
action and <Link>
component as usual.
data-method
: The HTTP methoddata-target
: A target framedata-preserve-scroll
: Preserve scrolldata-preserve-state
: Preserve statedata-preserve-url
: Preserve URLdata-replace
: Replace history state (instead of pushing new state)
Note that in frames other than the top frame, replace
and preserve-url
default to true
.
<a href="/session" data-method="delete">Log out</a>
The global router
and page
stores have been removed. Each frame now has its own router and page store. Get them from the frame component's context. Parent frame context is also available via inertia:frame_name
.
- import { router, page } from 'inertiax-svelte'
+ const { router, page } = getContext('inertia')
// OR
+ const { router, page } = getContext('inertia:_top')
For convenience, the current Frame's router is also passed to the Frame's component as a prop:
const { router } = $props()
When you use router.on('event', ...)
, you only receive events from that specific frame's router. To listen to events from all frames, use document.addEventListener('inertia:event', ...)
:
import { getContext } from "svelte";
const { router, frame } = getContext("inertia");
router.on("navigate", () => {
console.log("navigated inside frame ", frame);
})
// or listen to all frames:
document.addEventListener('inertia:navigate', ...)
Follow the installation guide for your backend adapter on https://inertiajs.com, but replace the @inertiajs/svelte
package with inertiax-svelte
.
npm i -D inertiax-svelte
Then use the package like you would use the original:
import { createInertiaApp } from 'inertiax-svelte'
createInertiaApp( ... ) {
// ...
}
The "secret sauce" is actually quite simple: Instead of one global router instance for your Inertia app, Inertia X creates one router instance per frame. The top-level app component is also a <Frame>
(the <App>
component has been removed in Inertia X).