Nested layouts
A route with children becomes a layout: its component renders, and you place an <Outlet> where the matched child should appear. The matched chain is rendered root → leaf, each layout pulling in the next via its Outlet.
Why layouts persist
Layout component identity is stable across child navigations — navigating from /dashboard/overview to /dashboard/settings keeps the same DashboardLayout instance mounted (and its state, scroll, focus). Only the <Outlet> content swaps.
Example
svelte
<!-- DashboardLayout.svelte -->
<script lang="ts">
import { Outlet } from "@isorouter/svelte";
</script>
<h1>Dashboard</h1>
<Outlet />tsx
import { Outlet } from "@isorouter/react";
function DashboardLayout() {
return (
<div>
<h1>Dashboard</h1>
<Outlet />
</div>
);
}ts
import { defineComponent, h } from "vue";
import { Outlet } from "@isorouter/vue";
const DashboardLayout = defineComponent({
render: () => h("div", [h("h1", "Dashboard"), h(Outlet)]),
});Wire it up with children. An index route renders at the layout's own URL:
ts
const router = createCoreRouter([
{
path: "/dashboard",
component: DashboardLayout,
children: [
{ index: true, component: Overview }, // /dashboard
{ path: "settings", component: Settings }, // /dashboard/settings
],
},
] as const);Behaviour notes
<Outlet>renders the next component in the matched chain at the current nesting depth, and renders nothing when there is no matching child.- A matched parent with no matching child still resolves on its own if the path is fully consumed (e.g.
/dashboardwith noindexroute just renders the layout with an emptyOutlet). - Routes with no
componentare matched as pass-through layouts — they group children under a path prefix without adding tosnapshot.components.