skills/foundation/umbraco-routing/SKILL.md
Understand and use routing in Umbraco backoffice (foundational concept)
npx skillsauth add albanist/umbraco_cli umbraco-routingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Routing in Umbraco's backoffice enables navigation between sections, dashboards, and workspaces using pathname-based URLs. Sections serve as primary organizational dividers with entry points via section views, dashboards, or custom elements. Custom routing can be built using umb-router-slot with route definitions that support parameters and redirects.
Always fetch the latest docs before implementing:
The Umbraco source includes a working example:
Location: /Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/modal-routed/
This example demonstrates routed modals with URL-based navigation and deep-linking support. Study this for complex routing patterns.
{
"type": "section",
"alias": "My.Section",
"name": "My Section",
"meta": {
"label": "My Section",
"pathname": "my-section"
}
}
URL: /section/my-section
{
"type": "dashboard",
"alias": "My.Dashboard",
"name": "My Dashboard",
"meta": {
"label": "Welcome",
"pathname": "welcome-dashboard"
},
"conditions": [
{
"alias": "Umb.Condition.SectionAlias",
"match": "Umb.Section.Content"
}
]
}
URL: /section/content/dashboard/welcome-dashboard
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
@customElement('my-routed-element')
export class MyRoutedElement extends UmbLitElement {
@state()
private _routes: UmbRoute[] = [
{
path: 'person/:personId',
component: () => import('./person.element.js'),
setup: (_component, info) => {
console.log('personId:', info.match.params.personId);
},
},
{
path: 'people',
component: () => import('./people.element.js'),
},
{
path: '',
redirectTo: 'people',
},
];
render() {
return html`
<umb-router-slot .routes=${this._routes}></umb-router-slot>
`;
}
}
{
path: 'edit/:id',
component: () => import('./edit.element.js'),
setup: (component, info) => {
const id = info.match.params.id;
component.itemId = id;
},
}
{
path: '',
redirectTo: 'overview',
}
@state()
private _routes: UmbRoute[] = [
{
path: 'overview',
component: () => import('./overview.element.js'),
},
{
path: 'settings',
component: () => import('./settings.element.js'),
},
{
path: 'item/:id',
component: () => import('./item-detail.element.js'),
setup: (component, info) => {
component.itemId = info.match.params.id;
},
},
{
path: '',
redirectTo: 'overview',
},
];
render() {
return html`
<nav>
<a href="/section/my-section/overview">Overview</a>
<a href="/section/my-section/settings">Settings</a>
<a href="/section/my-section/item/123">Item 123</a>
</nav>
<umb-router-slot .routes=${this._routes}></umb-router-slot>
`;
}
{
"type": "sectionView",
"alias": "My.SectionView",
"name": "My Section View",
"element": "/App_Plugins/MyExtension/section-view.js",
"meta": {
"label": "Organization",
"pathname": "organization",
"icon": "icon-users"
},
"conditions": [
{
"alias": "Umb.Condition.SectionAlias",
"match": "My.Section"
}
]
}
URL: /section/my-section/organization
// Parent element
@state()
private _routes: UmbRoute[] = [
{
path: 'admin',
component: () => import('./admin-layout.element.js'),
},
{
path: 'users',
component: () => import('./users-layout.element.js'),
},
];
// Admin layout element can have its own nested routes
@state()
private _adminRoutes: UmbRoute[] = [
{
path: 'dashboard',
component: () => import('./admin-dashboard.element.js'),
},
{
path: 'settings',
component: () => import('./admin-settings.element.js'),
},
];
{
path: 'edit/:documentId',
component: () => import('./document-editor.element.js'),
setup: (component, info) => {
// Access route parameters
const documentId = info.match.params.documentId;
// Pass to component
component.documentId = documentId;
// Can also access query params, etc.
console.log('Route info:', info);
},
}
pathname: URL segment for sections/dashboards/views
umb-router-slot: Component that renders matched route
UmbRoute: Route definition with path, component, setup
Route Order: First match wins - order matters!
Parameters: Use :paramName in path (e.g., item/:id)
Redirects: Use redirectTo to redirect to another path
setup Function: Called when route matches, receives component and route info
URL Structure:
/section/my-section/section/content/dashboard/welcome/section/my-section/organization/section/my-section/people/person/123Entry Points:
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.
tools
Umbraco Automate operations (event-driven workflow automation)
development
Webhook management (the Management API's outbound event notifications)
development
Backoffice user management (accounts, state, groups, API credentials)
tools
Backoffice user group management (permission sets)