skip to content

In Laravel with Inertia, what does Route::inertia register, and when should you use it instead of Inertia::render or the inertia() helper?

level: juniorimportance: should knowfreq 32%

answer

  1. a router macro, not a facade call
  2. GET and HEAD only
  3. Inertia\Controller reads route defaults
  4. static props, no route parameters
  5. inertia() with no arguments: the factory

basics

~20 s

Route::inertia($uri, $component, $props) registers a GET/HEAD route to Inertia's own invokable controller, which renders the component with fixed props. Use it for static pages; use Inertia::render or inertia() in a controller when props depend on the request.

solid answer

~40 s

`Route::inertia('/', 'welcome')` is a router macro the adapter registers. It matches `GET` and `HEAD`, points the route at the invokable `Inertia\Controller`, and stores the component name and props array in the route's defaults; the controller just calls `Inertia::render()` with them. It returns the `Route`, so `->name('home')` and `->middleware('auth')` chain as usual, and the starter kits use it for their welcome and dashboard pages. The props are fixed at registration: route parameters, bound models and queries are not passed in, so any page that needs request data gets a controller. There, `Inertia::render($component, $props)` and `inertia($component, $props)` are the same call; `inertia()` with no arguments returns the `ResponseFactory` itself, so `inertia()->location($url)` works too. The component may be a string or an enum case.

code

php · 14 lines
php
<?php

use App\Http\Controllers\PropertyController;
use Illuminate\Support\Facades\Route;

Route::inertia('/', 'welcome')->name('home');
Route::inertia('/help', 'Help', ['supportPhone' => '0113 496 0000'])->name('help');

Route::middleware('auth')->group(function () {
    Route::inertia('dashboard', 'dashboard')->name('dashboard');
    // Needs the bound model and a query, so it gets a controller:
    Route::get('/properties/{property}', [PropertyController::class, 'show'])
        ->name('properties.show');
});

go deeper

for a junior

Recall that Route::inertia serves a static page with fixed props and that Inertia::render and inertia() are the same call in a controller.

for a middle

Explain that the macro stores component and props in route defaults for Inertia\Controller, why route parameters never reach the props, and what inertia() returns with no arguments.

for a senior

Enforce component existence with pages.ensure_pages_exist or tests, and keep Route::inertia to pages that truly need no request data.

for a principal

Decide team conventions: enum page names, when routes-file pages are acceptable, and how page names stay in step with the frontend tree.

## Three ways to answer with a page The Laravel adapter gives you one factory, `Inertia\ResponseFactory`, and three entry points to it: | Entry point | Where you write it | Props come from | |---|---|---| | `Route::inertia($uri, $component, $props)` | a routes file | a fixed array given at registration | | `Inertia::render($component, $props)` | a controller or closure | anything computed for the request | | `inertia($component, $props)` | a controller or closure | same as `Inertia::render` | All three end in the same `Inertia\Response`, so the wire format, shared props and middleware behaviour are identical. ## What `Route::inertia` really registers `Route::inertia` is a **router macro** added by the adapter's service provider, not a method of Laravel's router. It does three things: 1. Registers a route that matches **`GET` and `HEAD`** only. 2. Points it at the invokable `Inertia\Controller`. 3. Stores the component and the props array in the route's **defaults** under `component` and `props`. When the route runs, `Inertia\Controller::__invoke()` calls `Inertia::render()` with those two defaults. Because the macro returns the `Route`, the usual chain works: - `Route::inertia('/', 'welcome')->name('home');` - `Route::inertia('dashboard', 'dashboard')` inside an `auth` middleware group, as the React starter kit does. ## The limit: nothing from the request The controller passes only the stored defaults. For the property-management dashboard that means: - `Route::inertia('/help', 'Help')` is a good fit: the page is static. - `Route::inertia('/properties/{property}', 'Properties/Show')` is a trap: the `{property}` parameter is not added to the props, and no model is bound into them, so the page receives only the fixed array plus shared props such as `errors` and `auth`. - Anything needing a query, a policy check, validation or the current user's data belongs in a controller. Shared props still arrive, because `HandleInertiaRequests` runs for the route like any other. ## `Inertia::render` and `inertia()` Inside a controller the facade and the helper are interchangeable. The helper has one extra shape: called with no component it returns the `ResponseFactory` instance, so `inertia()->share('portfolio', $name)` or `inertia()->location($url)` are valid. There is also an `inertia_location($url)` helper for the latter. The component argument may be: - a string such as `'Properties/Index'`; - a backed enum case, whose value is used; - a pure enum case, whose name is used. Anything else throws an `InvalidArgumentException`. ## Catching a misspelled component early By default the server never checks that `Properties/Index` exists as a file; a typo surfaces in the browser when the client cannot resolve the page. Setting `pages.ensure_pages_exist` to `true` in `config/inertia.php` makes `render()` look the name up under `pages.paths` (by default `resources/js/pages`) with the configured extensions, and throw `Inertia\ComponentNotFoundException` when it is missing. The separate `testing.ensure_pages_exist` option, `true` by default, makes the test assertion `component()` perform the same file check. ## Pitfalls seen in reviews - **Putting request logic in a routes-file closure instead of a controller.** `Route::get('/reports', fn () => Inertia::render('Reports', [...]))` works, but a controller keeps authorization, queries and tests in one discoverable place. - **Passing whole models as props.** A model passed to `render()` is converted with `toArray()`, so every attribute not hidden on the model is sent. Select the fields the page needs. - **Assuming a missing page fails on the server.** Without `pages.ensure_pages_exist`, the server happily returns a component name that does not exist, and only the browser notices. - **Computing values in `Route::inertia` props.** An array such as `['year' => now()->year]` is evaluated when the routes file is loaded. That happens on every request normally, but `php artisan route:cache` stores the route defaults, so the value freezes at cache time in production. Values that must be fresh belong in a controller. ## Choosing in practice - Static marketing, help or placeholder pages: `Route::inertia`. - Everything with data: a controller returning `Inertia::render` or `inertia()`, whichever the team's style guide prefers. - Enum component names are worth it when many controllers reference the same pages and you want refactors to be type-checked.

  • Does a Route::inertia route still receive shared props and run middleware?
    Yes. It is an ordinary route, so the `web` group, including `HandleInertiaRequests`, and any middleware you chain still run. Shared props such as `errors` and `auth` are merged in by the factory as for any `Inertia::render` call. Only the page-specific props are limited to the fixed array given at registration.
  • How do you make a misspelled page component fail on the server instead of in the browser?
    Set `pages.ensure_pages_exist` to `true` in `config/inertia.php`. `render()` then looks the component up under `pages.paths` with the configured extensions and throws `Inertia\ComponentNotFoundException` if no file matches. In tests, `testing.ensure_pages_exist` is already `true`, so `assertInertia`'s `component()` check fails for a missing file.

saying these in an interview costs you the question

  • Route::inertia passes route parameters to the page as props.
  • Route::inertia routes skip the web middleware group.
  • inertia() without arguments throws because a component is required.
  • Route::inertia is a Laravel core router method, not the adapter's macro.
  • The server always verifies that the page component file exists.