Layouts Within Layouts

As your application grows, different sections often need their own unique navigation or structure. The services section might need its own navigation — filtering by category, sorting options, or a sidebar. The about and contact pages probably don’t need this extra UI.

But here’s the challenge: you don’t want to lose the main header and footer that appear on every page. You just want to add section-specific UI, not replace the site-wide structure.

This is where nested layouts shine. They let you layer layouts on top of each other, so you can:

  • Keep site-wide UI (header/footer) consistent across all pages
  • Add section-specific UI (sidebar, sub-nav) only where needed
  • Avoid duplicating code or manually managing what appears where

Think of nested layouts like Russian nesting dolls — each layer wraps the next, building up the complete page structure from the outside in.

Real-World Example

Imagine you’re browsing an online store:

  • Every page has the same site header (logo, cart, account menu)
  • Product pages have category filters in a sidebar
  • Account pages have different navigation (orders, settings, wishlist)
  • Checkout pages have a simplified header with just essential info

Each section needs its own layout, but they all share the base site structure. Nested layouts make this pattern natural and maintainable.


What You’ll Learn

  • Create a layout specific to a route section
  • Understand how nested layouts inherit from parent layouts
  • Build sub-navigation for the services area

How Nesting Works

Layouts cascade. A layout in a subfolder wraps pages in that folder, but it’s also wrapped by any parent layouts:

src/routes/
├── +layout.svelte           ← Root layout (header/footer)
└── services/
    ├── +layout.svelte       ← Services layout (adds sub-nav)
    └── +page.svelte         ← Services page

When you visit /services:

  1. Root layout renders (header + footer)
  2. Services layout renders inside root layout’s {@render children()}
  3. Services page renders inside services layout’s {@render children()}
┌─────────────────────────────────────┐
│  Root Layout (header)               │
│  ┌───────────────────────────────┐  │
│  │  Services Layout (sub-nav)    │  │
│  │  ┌─────────────────────────┐  │  │
│  │  │  Services Page          │  │  │
│  │  └─────────────────────────┘  │  │
│  └───────────────────────────────┘  │
│  Root Layout (footer)               │
└─────────────────────────────────────┘

Create the Services Layout

Now it’s time to build the services-specific layout. This layout will add a category navigation sidebar to all pages under the /services route, while still inheriting the header and footer from the root layout.

What This Layout Will Provide

The services layout will create a two-column structure:

  • Left column: A persistent sidebar with category links
  • Right column: The page content (services list or individual service details)

This sidebar will appear on both /services (the list) and /services/[slug] (individual service pages), giving users a consistent way to filter or browse by category no matter where they are in the services section.

Understanding the Layout Structure

Before we write the code, let’s break down what this layout needs:

  1. Props destructuring: Accept the children prop from SvelteKit
  2. Sidebar navigation: A list of category links for filtering
  3. Content area: A wrapper that renders the child page content
  4. Flexbox layout: CSS to position sidebar and content side-by-side
  5. Responsive styling: Make it look clean and professional

Building the Layout

Create +layout.svelte inside the services folder:

<!-- filename: src/routes/services/+layout.svelte -->
<script>
	let { children } = $props()
</script>

<div class="services-layout">
	<aside class="services-nav">
		<h3>Categories</h3>
		<ul>
			<li><a href="/services">All Services</a></li>
			<li><a href="/services?category=lawn-care">Lawn Care</a></li>
			<li><a href="/services?category=tree-care">Tree Care</a></li>
			<li><a href="/services?category=consultation">Consultation</a></li>
			<li><a href="/services?category=cleaning">Cleaning</a></li>
		</ul>
	</aside>

	<div class="services-content">
		{@render children()}
	</div>
</div>

<style>
	.services-layout {
		display: flex;
		gap: 2rem;
	}

	.services-nav {
		width: 200px;
		flex-shrink: 0;
	}

	.services-nav h3 {
		margin: 0 0 1rem 0;
		font-size: 1rem;
		color: #666;
	}

	.services-nav ul {
		list-style: none;
		padding: 0;
		margin: 0;
	}

	.services-nav li {
		margin: 0.5rem 0;
	}

	.services-nav a {
		color: #333;
		text-decoration: none;
	}

	.services-nav a:hover {
		color: #007bff;
	}

	.services-content {
		flex: 1;
	}
</style>

This creates a two-column layout: category sidebar on the left, page content on the right.


Test the Nesting

Visit /services. You should see:

  1. Site header (from root layout)
  2. Category sidebar (from services layout)
  3. Services list (from services page)
  4. Site footer (from root layout)

Now visit /services/lawn-mowing. The same structure applies:

  1. Site header
  2. Category sidebar
  3. Service detail page
  4. Site footer

The services layout wraps both the list page and the detail pages.


Your Project Structure

src/routes/
├── +layout.svelte              ← Root (header, main, footer)
├── +page.svelte                ← Homepage
├── services/
│   ├── +layout.svelte          ← Services (sidebar) [NEW]
│   ├── +page.svelte            ← Services list
│   └── [slug]/
│       ├── +page.js
│       └── +page.svelte        ← Service detail
├── about/
│   └── +page.svelte            ← About (no extra layout)
└── contact/
    └── +page.svelte            ← Contact (no extra layout)

Pages in about/ and contact/ only get the root layout. Pages in services/ get both root and services layouts.


The Inheritance Chain

Every nested layout must also receive and render children:

<!-- Every layout needs this pattern -->
<script>
	let { children } = $props()
</script>

<!-- Your layout content -->
{@render children()}
<!-- More layout content if needed -->

The content passed as children to a nested layout is either:

  • Another nested layout (which will render its own children)
  • The actual page component

SvelteKit handles the chain automatically.


When to Use Nested Layouts

Nested layouts are useful for:

  • Section navigation — Sidebar or tabs within a section
  • Different page structures — Dashboard with sidebar vs marketing pages without
  • Shared data loading — Load user data once for all account pages
  • Scoped styling — Apply styles only to certain routes

You don’t need nested layouts for every folder. Only create them when a section genuinely needs different wrapping.


Common Mistakes

Forgetting Children in Nested Layout

<!-- ❌ Page content disappears -->
<script>
	let { children } = $props()
</script>

<aside class="sidebar">Navigation</aside>
<!-- Missing: {@render children()} -->

Every layout must render its children, or the content below it in the chain won’t appear.

Creating Empty Layouts

<!-- ❌ Pointless — adds nothing -->
<script>
	let { children } = $props()
</script>

{@render children()}

If a layout just passes through children with no additions, delete it. SvelteKit doesn’t require layouts in every folder.


Summary

Nested layouts let you add section-specific UI while inheriting parent layouts. The services section now has a category sidebar that appears on all services pages, while still keeping the site-wide header and footer.

Key takeaways:

  • Layouts in subfolders nest inside parent layouts
  • Each layout must receive and render children
  • Only create nested layouts when sections need unique wrapping

Module Complete! 🎉

You’ve finished Module 3: Layouts. BookIt now has:

  • Root layout with header and footer on all pages
  • Services layout with category sidebar
  • Clean, DRY code — navigation defined once
  • Proper nesting structure

What you’ve learned:

  • Why repeating code is problematic (DRY principle)
  • Creating +layout.svelte files
  • The children snippet and {@render children()}
  • Building headers and footers
  • Nesting layouts for section-specific UI

Next Steps

Continue with Module 4: Reactivity Basics (already complete!) where you’ll build an interactive booking form with live preview using $state.