Documentation / @zerotal/inertia / Inertia
Variable: Inertia
constInertia:object
Defined in: inertia/src/facades/Inertia.ts:24
Unified Inertia facade.
Type Declaration
Other
render
readonlyrender: (component,props) =>Promise<void> =inertia
Render an Inertia page (= the inertia() helper).
Render an Inertia page from a controller action — the primary way to return a page from Zerotal's Inertia adapter.
You name a client-side page component and hand it a bag of props; Inertia takes
care of showing that component with those props, so you build a React/Vue SPA
without writing a separate JSON API. The component name is a path (relative to
the configured pages dir, without extension) resolving to a page under
resources/js/pages, e.g. "Users/Index" → resources/js/pages/Users/Index.tsx.
Parameters
component
string
Page component name/path relative to the pages dir, without extension (e.g. "Users/Index").
props?
Record<string, unknown> = {}
Props for the page. Values may be plain data or prop wrappers (optional/defer/merge/scroll/…). Defaults to {}.
Returns
Promise<void>
A promise that resolves once ctx.response has been set (no value).
Remarks
Reads the current request from RequestContext (AsyncLocalStorage) — no ctx
argument needed — and assigns the outgoing Response to ctx.response as a side
effect, hence the Promise<void> return. The two response shapes it produces are
what "Inertia" means on the wire:
- First / full-page load (no
X-Inertiaheader): the full HTML shell from the app template with the page object serialised into a<script data-page>tag (HTML-escaped so it can't break out of the script). The client-side Inertia runtime boots from it. - Subsequent visits (
X-Inertia: trueXHR): a JSON body containing only the page object, carryingX-Inertia: trueandVary: X-Inertia(the latter stops the browser from caching JSON as HTML and rendering raw JSON on Back/Refresh).
Before responding, props are run through the Inertia v3 resolution pipeline (see
buildPageObject / resolveProps): the app's shared props (auth, flash,
errors, plus anything from share) are merged in; partial reloads honour
the client's only/except headers so a visit can refetch just a few props; and
prop wrappers control evaluation — plain values are sent as-is, functions and
optional/lazy/defer props are evaluated only when actually included (deferred
ones load in a follow-up request), while always, merge/deepMerge, scroll,
and once props are advertised so the client merges rather than replaces.
For streaming SSR (better TTFB) use inertiaStream instead; to force a full-page/external redirect use location.
Throws
InertiaTemplateNotLoadedError On a full-page load when the HTML template has not been loaded (InertiaProvider not registered).
Example
// app/controllers/UserController.ts
async index(http: HttpContext): Promise<void> {
const users = await User.query().orderBy('name').get();
return inertia('Users/Index', { users });
}
stream
readonlystream: (component,props) =>Promise<void> =inertiaStream
Render an Inertia page using React streaming SSR.
Render an Inertia page server-side and return a streaming HTML Response.
Splits the HTML template at <!-- @inertia --> and writes the server-rendered
component between the prefix and suffix, improving TTFB over inertia() since
the browser can start parsing the <head> before the component is sent.
Framework-aware: React pages (.tsx) stream chunk-by-chunk via
react-dom/server's renderToReadableStream; Vue pages (.vue) are rendered
to a string via @inertiajs/vue3's SSR mode (head tags injected into
<head>) and flushed after the prefix. The component is resolved from
<cwd>/<inertia.pagesDir>/<component>.{vue,tsx} (defaults to resources/js/pages).
Like inertia, this reads the current request from RequestContext and
writes the streaming Response onto ctx.response as a side effect (returns void).
Reach it from a controller via Inertia.stream(...).
Parameters
component
string
Page component name (path relative to the pages dir, no extension), e.g. "Posts/Show".
props?
Record<string, unknown> = {}
Props passed to the page; may include prop wrappers (optional/defer/merge/…).
Returns
Promise<void>
Throws
InertiaTemplateNotLoadedError When the HTML template has not been loaded (InertiaProvider not registered).
Throws
InvalidComponentError When the component name contains path-traversal sequences.
Example
async show(http: HttpContext): Promise<void> {
const post = await Post.findOrFail(http.params.id);
return Inertia.stream('Posts/Show', { post });
}
share
share: {(
key,value):void; (values):void; }
Register shared props included on every page.
Call Signature
(
key,value):void
Register shared prop(s) that Zerotal includes on every Inertia page, so page components can read them without each controller passing them explicitly.
Parameters
key
string
The shared prop name (single-key overload) — or, in the object overload, the map of names to values.
value
unknown
The value for key (single-key overload only); a plain value, a per-request factory, or a prop wrapper.
Returns
void
Remarks
Call once at boot (typically in a service provider) — a later share() of the
same key overwrites the previous value. Values may be plain data, a factory
function (re-evaluated lazily per request, e.g. to read the current user), or a
prop wrapper. The built-in shared keys (auth, flash, errors, old) are
always present in addition to whatever you register here; see sharedProps.
Two call styles: a single key/value pair, or an object of many at once.
Example
// In a service provider's boot() — available on every page (auth/flash/errors/old
// are already built in; register your own extras here).
Inertia.share({
appName: 'Acme',
permissions: () => Auth.user()?.permissions ?? [], // factory re-runs each request
});
// Or a single key:
Inertia.share('year', () => new Date().getFullYear());
Call Signature
(
values):void
Register shared prop(s) that Zerotal includes on every Inertia page, so page components can read them without each controller passing them explicitly.
Parameters
values
Record<string, unknown>
Returns
void
Remarks
Call once at boot (typically in a service provider) — a later share() of the
same key overwrites the previous value. Values may be plain data, a factory
function (re-evaluated lazily per request, e.g. to read the current user), or a
prop wrapper. The built-in shared keys (auth, flash, errors, old) are
always present in addition to whatever you register here; see sharedProps.
Two call styles: a single key/value pair, or an object of many at once.
Example
// In a service provider's boot() — available on every page (auth/flash/errors/old
// are already built in; register your own extras here).
Inertia.share({
appName: 'Acme',
permissions: () => Auth.user()?.permissions ?? [], // factory re-runs each request
});
// Or a single key:
Inertia.share('year', () => new Date().getFullYear());
encryptHistory
encryptHistory: (
on) =>void
Encrypt the current page's browser history state.
Encrypt the current page's history state in the browser (protects props cached in
history.state for a page holding sensitive data). Effective for the current request.
Parameters
on?
boolean = true
Pass false to opt this page out when encryption is the global default. Default true.
Returns
void
Example
async show(http: HttpContext): Promise<void> {
Inertia.encryptHistory();
return inertia('Account/Settings', { account });
}
clearHistory
clearHistory: () =>
void
Clear any encrypted history state (e.g. on logout).
Clear any previously encrypted history state — call on logout so cached page data can't be recovered via the browser Back button.
Returns
void
Example
async destroy(http: HttpContext): Promise<void> {
await Auth.logout();
Inertia.clearHistory();
return redirect('/login');
}
location
location: (
url) =>void
External redirect (full-page visit).
Redirect to an external URL, or force a full-page (non-Inertia) visit to an internal one.
Parameters
url
string
The absolute or relative URL to send the browser to.
Returns
void
Remarks
A normal Inertia visit expects a JSON page object, so it cannot follow an ordinary
redirect off the SPA. For an Inertia XHR this helper responds 409 Conflict with an
X-Inertia-Location header, which
tells the client to do a hard window.location navigation; for a plain request it
responds with a standard 302 redirect. Use it for third-party URLs (payment
portals, OAuth providers) or any target that must leave the SPA.
Reads the current request from RequestContext and sets ctx.response as a side
effect (returns void), like inertia.
Example
// Send the user off to an external billing portal.
async billing(http: HttpContext): Promise<void> {
const session = await stripe.createBillingSession(Auth.id());
return location(session.url);
}
Props
optional
optional: (
callback) =>OptionalProp
Prop only included when explicitly requested via a partial reload's only.
Never include this prop on a full visit; the callback runs (and the value is sent)
only when a partial reload names the key in its only set. Use for expensive data
a page fetches on demand.
Parameters
callback
Factory producing the prop value (may be async); evaluated only when included.
Returns
An OptionalProp wrapper for the resolver.
Example
return inertia('Users/Index', {
users,
// Only fetched when the client does `router.reload({ only: ['stats'] })`.
stats: optional(() => computeExpensiveStats()),
});
lazy
lazy: (
callback) =>OptionalProp
Alias of optional.
Alias of optional, matching Inertia's historical lazy() name.
Parameters
callback
Factory producing the prop value (may be async); evaluated only when included.
Returns
An OptionalProp wrapper.
always
always: (
value) =>AlwaysProp
Prop always included, even on partial reloads that would otherwise exclude it.
Always include this prop, even when a partial reload's only/except would
otherwise exclude it. Used internally to keep the errors bag present on every visit.
Parameters
value
unknown
The value, or a factory producing it (evaluated when included).
Returns
An AlwaysProp wrapper.
defer
defer: (
callback,group,options) =>DeferProp
Prop deferred to a follow-up request after the initial render.
Exclude this prop from the initial render and load it in an automatic follow-up
request, so the page paints immediately and heavier data streams in after. Props
sharing a group are fetched together in one request.
Parameters
callback
Factory producing the prop value (may be async); runs on the deferred request.
group?
string = "default"
Request group name; props with the same group load in one follow-up request. Default "default".
options?
rescue: true swallows a thrown error and reports the key in rescuedProps instead of failing the request.
rescue?
boolean
Returns
A DeferProp wrapper.
Example
return inertia('Dashboard', {
user,
stats: defer(() => computeStats()), // group "default"
activity: defer(() => recentActivity(), 'secondary'), // separate request
});
merge
merge: (
value) =>MergeProp
Prop the client appends (merges) into existing data on partial reloads.
Mark this prop so the client appends (merges) it into the existing value on partial
reloads instead of replacing it — the basis for "load more" lists. Chain
.append() / .prepend() / .matchOn() on the returned wrapper for finer control.
Parameters
value
unknown
The value, or a factory producing it.
Returns
A MergeProp wrapper.
Example
return inertia('Feed', { posts: merge(() => Post.paginate(15, page)) });
deepMerge
deepMerge: (
value) =>MergeProp
Prop the client deep-merges into existing data on partial reloads.
Like merge, but the client deep-merges the structure into the existing prop value on partial reloads rather than appending at the root.
Parameters
value
unknown
The value, or a factory producing it.
Returns
A MergeProp wrapper configured for deep merging.
scroll
scroll: (
value,options) =>InfiniteScrollProp
Infinite-scroll prop: merges paginated data and emits scroll metadata.
Infinite-scroll prop: merges paginated data and emits scrollProps so the client
<InfiniteScroll> component knows when to load the next/previous page.
Parameters
value
A paginator (or factory producing one) with data plus page metadata.
options?
pageName (query param driving pagination, default "page") and dataPath (path to the array to merge, default "data").
pageName?
string
dataPath?
string
Returns
An InfiniteScrollProp wrapper.
Example
return inertia('Posts/Index', { posts: scroll(() => Post.paginate(15, page)) });
// custom page-query name:
return inertia('Items', { items: scroll(() => Item.paginate(15, page), { pageName: 'p' }) });
Example
import { Inertia } from "@zerotal/inertia";
async index(http: HttpContext) {
return Inertia.render("Users/Index", {
users: Inertia.optional(() => User.all()), // only on partial reload
stats: Inertia.defer(() => computeStats()), // loaded after first paint
feed: Inertia.merge(() => Post.paginate()), // append on "load more"
});
}
Standalone helpers (`optional`, `always`, `defer`, `merge`, `deepMerge`, `lazy`) are also exported
for direct import if you prefer not to go through the facade.