In Laravel with Inertia, what does Route::inertia register, and when should you use it instead of Inertia::render or the inertia() helper?
answer
- a router macro, not a facade call
- GET and HEAD only
- Inertia\Controller reads route defaults
- static props, no route parameters
- inertia() with no arguments: the factory
basics
~20 sRoute::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
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
Recall that Route::inertia serves a static page with fixed props and that Inertia::render and inertia() are the same call in a controller.
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.
Enforce component existence with pages.ensure_pages_exist or tests, and keep Route::inertia to pages that truly need no request data.
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.