Routes Reference
Every route in a LaravelUi5 installation lives under one of two prefixes: ui5/ for artifacts and the shell, odata/ for reads. This page lists what is registered and, more usefully, which middleware stack each route runs — that is what decides who gets a 200 and who gets a 403.
php artisan route:list --path=ui5 shows the live set in your own installation.
Who registers what
| Package | Route file | Prefix | Stack |
|---|---|---|---|
| Core | routes/ui5.php | ui5 | config('ui5.middleware') |
| SDK | routes/ui5-sdk.php | ui5 | config('ui5.middleware') |
| SDK | routes/ui5-sdk-web.php | ui5 | ['web', 'auth'] |
| OData engine | Core loads the engine's route file (the engine's own registration is switched off) | odata | config('ui5.odata_middleware') |
The third row is the one to remember, and the request edge explains why.
Core — the artifact routes
Core's model is one canonical shape: {type}/{namespace}@{version}/…. The namespace may contain slashes; the version is explicit and pinned to \d+\.\d+\.\d+.
| Method | Path | Serves |
|---|---|---|
| GET | ui5/app/{namespace}@{version}/index.html | The app's bootstrap page (named route ui5.app) |
| GET | ui5/app/{namespace}@{version}/manifest.json | The app manifest, with the OData data source injected |
| GET | ui5/card/{namespace}@{version}/manifest.json | An integration card's manifest |
| GET | ui5/card/{namespace}@{version}/i18n/{file} | A card's own .properties bundle |
| GET | ui5/dashboard/{namespace}@{version}/manifest.json | A dashboard's declared control tree |
| GET | ui5/report/{namespace}@{version} | A server-rendered report document (Cache-Control: no-store) |
| GET | ui5/resource/{namespace}@{version} | A resource artifact |
| POST · PATCH · DELETE | ui5/api/{namespace}@{version}/{uri?} | Action dispatch — every write in the system |
| GET | ui5/{app|lib}/{namespace}@{version}/{file} | Static assets: bundles, -dbg.js, source maps, fragments |
The @{version} segment is a cache buster, not a selector. The registry is keyed by namespace alone, so there are never two versions side by side — a mismatched version does not reach an older build, it simply misses the cache.
SDK — the shell routes
Artifact-scoped: each carries the app's {slug} (its namespace), so ResolveUi5Context can bind the context before the controller runs.
| Method | Path | Name | Serves |
|---|---|---|---|
| GET | ui5/shell/{slug}/context.json | ui5.shell.context | The live shell context — actor, principal, abilities, navigation, actions, settings, weave |
| GET | ui5/shell/{slug}/search.json | ui5.shell.search | Command-palette results for a query |
| POST | ui5/shell/{slug}/intend.json | ui5.shell.intent.dispatch | Intent dispatch |
| POST | ui5/export/{slug} | ui5.export | Table export — streams a file |
SDK — the help routes and the shell assets
Not artifact-scoped, and that is deliberate: one compiled help index serves every module and one shell bundle serves every app, so these paths carry no artifact. They therefore cannot run the artifact stack — ResolveUi5Context demands a resolvable artifact and would 404 them. They run ['web', 'auth'] instead: signed in, no ability check.
| Method | Path | Name | Serves |
|---|---|---|---|
| GET | ui5/help/toc.html | ui5.help.toc | The compiled table of contents |
| GET | ui5/help/index.json | ui5.help.index | The Lunr full-text index |
| GET | ui5/help/{uuid}/{name} | ui5.help.document | A help document ({name} = a locale) or one of its assets |
| GET | ui5/shell/{version}/main.esm.js | ui5.shell.script | The LeanShell bundle, served from the package |
| GET | ui5/shell/{version}/style.css | ui5.shell.style | The LeanShell stylesheet, served from the package |
The shell's {version} is the SDK package version, and like Core's @{version} it is a cache buster: an upgrade changes the URL, so no browser or proxy keeps the old bundle. That is why both answer with Cache-Control: private, max-age=31536000, immutable. Since SDK 1.2.0; before, the bundle was copied into public/sdk under a fixed path.
One more route, and it is load-bearing
GET /ui5/dashboard → redirect to the LaunchpadRegistered by the SDK in routes/ui5-sdk-web.php, so it shares that file's ui5 prefix and its ['web', 'auth'] stack. What matters is the name, dashboard: laravelui5/auth's intent dispenser falls back to route('dashboard') when a sign-in has no intended URL, and the impersonation handler lands here too. Link to it by name, never by path.
It must land on the Launchpad, which is auth-only with no #[Access] gate. The reason is the impersonation case: an impersonated partner may have access to no particular app, so landing on a gated app could strand the session in a 403 with nowhere to go. The Launchpad shows only what the acting partner may reach, so a transition can never dead-end.
What is not here
- No route publishes. The SDK's route files load from the package. You do not copy them into your app, and there is no
vendor:publishtag for them. - No per-app route file. An app contributes routes by declaring artifacts; the canonical paths above serve them. An action's
{uri?}segment is the only place an app shapes a path itself. - No CRUD routes. OData is read-only in LaravelUi5; every write is an action on
ui5/api/….