Skip to main content
zerotal

Documentation


Documentation / @zerotal/inertia / Inertia

Variable: Inertia

const Inertia: object

Defined in: inertia/src/facades/Inertia.ts:24

Unified Inertia facade.

Type Declaration

Other

render

readonly render: (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-Inertia header): 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: true XHR): a JSON body containing only the page object, carrying X-Inertia: true and Vary: 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

readonly stream: (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

PropFactory

Factory producing the prop value (may be async); evaluated only when included.

Returns

OptionalProp

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

PropFactory

Factory producing the prop value (may be async); evaluated only when included.

Returns

OptionalProp

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

AlwaysProp

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

PropFactory

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

DeferProp

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

MergeProp

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

MergeProp

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

PropFactory | PaginatorLike

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

InfiniteScrollProp

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.