Layouts and Navigation
In React Router you compose layouts by nesting <Outlet /> inside a parent route component — any child route renders where you place the outlet. SvelteKit takes a file-system approach instead: a +layout.svelte file automatically wraps every route in the same directory. You get the same nesting behaviour, but without any explicit route configuration.
Run this in a SvelteKit project (
npx sv create).
Layout with nested routes
Section titled “Layout with nested routes”In React Router you mark where children render by placing <Outlet />. In SvelteKit Svelte 5, layouts use the snippet syntax {@render children()} — there is no <slot /> in Svelte 5 layouts.
// src/layouts/RootLayout.jsx (React Router v6)import { Outlet, Link } from 'react-router-dom';
export default function RootLayout() { return ( <div> <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> <Link to="/blog">Blog</Link> </nav> <main> <Outlet /> </main> </div> );}<!-- src/routes/+layout.svelte --><script> let { children } = $props();</script>
<nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/blog">Blog</a></nav>
<main> {@render children()}</main>{@render children()} is where the matched child route renders. The children snippet is provided automatically by SvelteKit — you just destructure it from $props().
Active link highlighting
Section titled “Active link highlighting”React Router gives you useLocation() to read the current URL and derive active styles. SvelteKit exposes the same information through the page object imported from $app/state.
// React Router — active link with useLocationimport { Link, useLocation } from 'react-router-dom';
const links = [ { to: '/', label: 'Home' }, { to: '/about', label: 'About' }, { to: '/blog', label: 'Blog' },];
export default function Nav() { const { pathname } = useLocation();
return ( <nav> {links.map(({ to, label }) => ( <Link key={to} to={to} className={pathname === to ? 'active' : ''} > {label} </Link> ))} </nav> );}<!-- +layout.svelte (Svelte 5) --><script> import { page } from '$app/state'; let { children } = $props();
const links = [ { href: '/', label: 'Home' }, { href: '/about', label: 'About' }, { href: '/blog', label: 'Blog' }, ];</script>
<nav> {#each links as { href, label }} <a {href} class:active={page.url.pathname === href}> {label} </a> {/each}</nav>
<main> {@render children()}</main>
<style> a { margin-right: 1rem; text-decoration: none; color: inherit; } a.active { font-weight: bold; border-bottom: 2px solid currentColor; }</style>page from $app/state is a reactive object — it updates on every navigation automatically. No useEffect, no subscription setup.
Full +layout.svelte with active-link navigation
Section titled “Full +layout.svelte with active-link navigation”Here is a complete layout you can drop into any SvelteKit project:
<script> import { page } from '$app/state'; let { children } = $props();</script>
<header> <a href="/" class="logo">MySite</a> <nav> <a href="/" class:active={page.url.pathname === '/'}>Home</a> <a href="/about" class:active={page.url.pathname === '/about'}>About</a> <a href="/blog" class:active={page.url.pathname.startsWith('/blog')}>Blog</a> </nav></header>
<main> {@render children()}</main>
<footer>© 2026 MySite</footer>
<style> header { display: flex; align-items: center; gap: 1rem; padding: 0.75rem 1.5rem; border-bottom: 1px solid #e5e7eb; } .logo { font-weight: 700; text-decoration: none; } nav { display: flex; gap: 1rem; margin-left: auto; } nav a { text-decoration: none; color: inherit; } nav a.active { font-weight: 600; color: #FF3E00; }</style>Key points
Section titled “Key points”+layout.sveltewraps all routes in the same directory — and nested directories inherit it automatically.- Children render at
{@render children()}(Svelte 5 snippet syntax). There is no<slot />in Svelte 5 layouts. - Layouts nest:
dashboard/+layout.sveltewraps all routes under/dashboard, inside the root layout.
flowchart TB routes(["src/routes/"]) routes --> rootLayout["+layout.svelte (root layout — nav + footer)"] routes --> rootPage["+page.svelte → /"] routes --> dashboard["dashboard/"] dashboard --> dashLayout["+layout.svelte (dashboard layout — sidebar)"] dashboard --> dashPage["+page.svelte → /dashboard"] dashboard --> settings["settings/"] settings --> settingsPage["+page.svelte → /dashboard/settings"]
- Use plain
<a href="/about">— no<Link>component needed. SvelteKit intercepts<a>clicks and performs client-side navigation automatically. pagefrom$app/stateprovidesurl,params,data,route.id, and more — all reactive.page.url.pathnameis the idiomatic way to implement active-link logic.