Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
menu
  1. Home
  2. /Web Development
  3. /Nextjs
  4. /Nested Layouts
Your Progress0%
0 of 70 completed

NextJS Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication

Nested Layouts

Creating sophisticated layout hierarchies for complex applications

The root layout handles global UI, but what about sections that need their own unique layouts? A blog might need a sidebar, a dashboard needs navigation tabs, and admin pages require different headers. Nested layouts let you create layout hierarchies where each level adds its own UI layer. Layouts wrap inside layouts, all the way from root to page, giving you incredible flexibility to build sophisticated applications with clear separation of concerns.

How Nested Layouts Work

When you create a layout in a subfolder, it wraps all pages in that folder and its children:

PLAINTEXT
app/
  layout.tsx              ← Root layout
  blog/
    layout.tsx            ← Blog layout
    page.tsx              β†’ /blog
    [slug]/
      page.tsx            β†’ /blog/my-post

When visiting a page, layouts nest from root to leaf:

URL: /blog/my-post

Rendering hierarchy:

PLAINTEXT
<RootLayout>
  <BlogLayout>
    <BlogPostPage />
  </BlogLayout>
</RootLayout>

Basic Nested Layout Structure

Blog section has its own layout nested under root

appImportant

Select a file or folder to see details

Key Concept: Composition

Each layout receives children which contains the next layer (either another layout or the page). This creates a composition pattern:

  • Root layout wraps everything
  • Section layouts wrap their subsections
  • Pages are the innermost children

Creating Your First Nested Layout

Let's build a blog with a sidebar that only shows on blog pages:

Step 1: Root Layout (Already Exists)

app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {/* Global header */}
        <header className="bg-blue-600 text-white p-4">
          <nav>Site Navigation</nav>
        </header>
        
        {/* Page content (may include nested layouts) */}
        <main>{children}</main>
        
        {/* Global footer */}
        <footer className="bg-gray-800 text-white p-4">
          Footer
        </footer>
      </body>
    </html>
  );
}

Step 2: Create Blog Layout

app/blog/layout.tsx
import Link from 'next/link';

export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="container mx-auto px-4 py-8">
      <div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
        {/* Sidebar - only shows on blog pages */}
        <aside className="lg:col-span-1">
          <div className="bg-white rounded-lg shadow p-6 sticky top-4">
            <h3 className="font-bold text-lg mb-4">Categories</h3>
            <nav className="space-y-2">
              <Link 
                href="/blog/category/tech"
                className="block text-blue-600 hover:underline"
              >
                Technology
              </Link>
              <Link 
                href="/blog/category/design"
                className="block text-blue-600 hover:underline"
              >
                Design
              </Link>
              <Link 
                href="/blog/category/business"
                className="block text-blue-600 hover:underline"
              >
                Business
              </Link>
            </nav>
            
            <h3 className="font-bold text-lg mt-6 mb-4">Recent Posts</h3>
            <div className="space-y-3 text-sm">
              <Link 
                href="/blog/post-1"
                className="block text-gray-700 hover:text-blue-600"
              >
                Understanding Layouts
              </Link>
              <Link 
                href="/blog/post-2"
                className="block text-gray-700 hover:text-blue-600"
              >
                Server Components Guide
              </Link>
              <Link 
                href="/blog/post-3"
                className="block text-gray-700 hover:text-blue-600"
              >
                Dynamic Routing Explained
              </Link>
            </div>
            
            <h3 className="font-bold text-lg mt-6 mb-4">Subscribe</h3>
            <input 
              type="email" 
              placeholder="Your email"
              className="w-full px-3 py-2 border rounded mb-2"
            />
            <button className="w-full bg-blue-600 text-white py-2 rounded">
              Subscribe
            </button>
          </div>
        </aside>

        {/* Main content - blog pages render here */}
        <main className="lg:col-span-3">
          {children}
        </main>
      </div>
    </div>
  );
}

Step 3: Create Blog Pages

app/blog/page.tsx
export default function BlogPage() {
  return (
    <div>
      <h1 className="text-4xl font-bold mb-6">Latest Blog Posts</h1>
      <div className="space-y-6">
        {/* Blog posts list */}
      </div>
    </div>
  );
}
app/blog/[slug]/page.tsx
export default function BlogPostPage({ 
  params 
}: { 
  params: { slug: string } 
}) {
  return (
    <article>
      <h1 className="text-4xl font-bold mb-4">
        {params.slug}
      </h1>
      <div className="prose max-w-none">
        {/* Post content */}
      </div>
    </article>
  );
}

✨ What Happens

When you visit blog pages:

  • /blog - Has header, footer, AND sidebar
  • /blog/my-post - Has header, footer, AND sidebar
  • /about - Has header and footer, NO sidebar

Multi-Level Nesting

You can nest layouts as deeply as needed:

PLAINTEXT
app/
  layout.tsx                        ← Level 1: Global
  dashboard/
    layout.tsx                      ← Level 2: Dashboard
    page.tsx
    analytics/
      layout.tsx                    ← Level 3: Analytics tabs
      page.tsx
      revenue/
        page.tsx

Complex Multi-Level Nesting

Three levels of nested layouts

appImportant

Select a file or folder to see details

Example: Dashboard with Sub-navigation

app/dashboard/layout.tsx
import Link from 'next/link';

// Level 2: Dashboard layout with sidebar
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex h-screen">
      {/* Dashboard sidebar */}
      <aside className="w-64 bg-gray-900 text-white p-6">
        <h2 className="text-xl font-bold mb-6">Dashboard</h2>
        <nav className="space-y-2">
          <Link 
            href="/dashboard"
            className="block px-4 py-2 rounded hover:bg-gray-800"
          >
            πŸ“Š Overview
          </Link>
          <Link 
            href="/dashboard/analytics"
            className="block px-4 py-2 rounded hover:bg-gray-800"
          >
            πŸ“ˆ Analytics
          </Link>
          <Link 
            href="/dashboard/users"
            className="block px-4 py-2 rounded hover:bg-gray-800"
          >
            πŸ‘₯ Users
          </Link>
          <Link 
            href="/dashboard/settings"
            className="block px-4 py-2 rounded hover:bg-gray-800"
          >
            βš™οΈ Settings
          </Link>
        </nav>
      </aside>

      {/* Main dashboard content */}
      <main className="flex-1 overflow-auto">
        {children}
      </main>
    </div>
  );
}
app/dashboard/analytics/layout.tsx
import Link from 'next/link';

// Level 3: Analytics layout with tabs
export default function AnalyticsLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="p-8">
      <h1 className="text-3xl font-bold mb-6">Analytics</h1>
      
      {/* Tab navigation */}
      <nav className="border-b mb-8">
        <div className="flex gap-6">
          <Link 
            href="/dashboard/analytics"
            className="pb-2 border-b-2 border-transparent hover:border-blue-600"
          >
            Overview
          </Link>
          <Link 
            href="/dashboard/analytics/revenue"
            className="pb-2 border-b-2 border-transparent hover:border-blue-600"
          >
            Revenue
          </Link>
          <Link 
            href="/dashboard/analytics/users"
            className="pb-2 border-b-2 border-transparent hover:border-blue-600"
          >
            Users
          </Link>
          <Link 
            href="/dashboard/analytics/traffic"
            className="pb-2 border-b-2 border-transparent hover:border-blue-600"
          >
            Traffic
          </Link>
        </div>
      </nav>

      {/* Analytics content */}
      {children}
    </div>
  );
}

Now the rendering hierarchy for /dashboard/analytics/revenue is:

PLAINTEXT
<RootLayout>              ← Header + Footer
  <DashboardLayout>        ← Sidebar
    <AnalyticsLayout>      ← Tabs
      <RevenuePage />
    </AnalyticsLayout>
  </DashboardLayout>
</RootLayout>

Metadata in Nested Layouts

Nested layouts can define their own metadata, which merges with or overrides parent metadata:

app/layout.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: {
    template: '%s | My App',  // Template for all pages
    default: 'My App',
  },
  description: 'My awesome application',
};
app/blog/layout.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: {
    template: '%s | Blog | My App',  // Override template for blog
    default: 'Blog | My App',
  },
  description: 'Read our latest blog posts',
  openGraph: {
    type: 'website',
    siteName: 'My App Blog',
  },
};

Now blog pages get the blog-specific metadata:

  • /about β†’ "About Us | My App" (root template)
  • /blog β†’ "Blog | My App" (blog default)
  • /blog/my-post β†’ "My Post | Blog | My App" (blog template)

Layout State Persistence

A key benefit of nested layouts is that their state persists when navigating between sibling pages:

app/blog/layout.tsx
'use client';

import { useState } from 'react';
import Link from 'next/link';

export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  // This state persists across blog page navigations!
  const [sidebarOpen, setSidebarOpen] = useState(true);

  return (
    <div className="flex">
      {/* Toggle button */}
      <button
        onClick={() => setSidebarOpen(!sidebarOpen)}
        className="fixed top-20 left-4 z-10 bg-blue-600 text-white p-2 rounded"
      >
        {sidebarOpen ? '←' : 'β†’'}
      </button>

      {/* Sidebar */}
      {sidebarOpen && (
        <aside className="w-64 p-6">
          <nav className="space-y-2">
            <Link href="/blog/post-1">Post 1</Link>
            <Link href="/blog/post-2">Post 2</Link>
            <Link href="/blog/post-3">Post 3</Link>
          </nav>
        </aside>
      )}

      {/* Content */}
      <main className="flex-1">
        {children}
      </main>
    </div>
  );
}

When navigating from /blog/post-1 to /blog/post-2:

  • βœ… The layout doesn't re-render
  • βœ… sidebarOpen state persists
  • βœ… Only the page content changes
  • βœ… Smooth, fast navigation

When State Resets

Layout state only persists when:

  • Navigating between pages under the same layout
  • The layout itself doesn't change

If you navigate to a different section (e.g., /blog to /about), the blog layout unmounts and state is lost.

Common Nested Layout Patterns

1. Marketing + Dashboard Structure

PLAINTEXT
app/
  layout.tsx                  ← Root: Basic HTML structure
  (marketing)/
    layout.tsx                ← Marketing: Header + Footer
    page.tsx                  β†’ /
    about/
      page.tsx                β†’ /about
    pricing/
      page.tsx                β†’ /pricing
  dashboard/
    layout.tsx                ← Dashboard: Sidebar + Top bar
    page.tsx                  β†’ /dashboard
    analytics/
      page.tsx                β†’ /dashboard/analytics

2. Docs with Sidebar + TOC

PLAINTEXT
app/
  layout.tsx                  ← Root: Global nav
  docs/
    layout.tsx                ← Docs: Sidebar navigation
    [section]/
      layout.tsx              ← Section: Table of contents
      [page]/
        page.tsx

3. E-commerce with Different Layouts

PLAINTEXT
app/
  layout.tsx                  ← Root: Site header
  (shop)/
    layout.tsx                ← Shop: Cart widget
    products/
      page.tsx
    cart/
      page.tsx
  checkout/
    layout.tsx                ← Checkout: Minimal, focused
    page.tsx

4. Multi-Tenant Application

PLAINTEXT
app/
  layout.tsx                  ← Root: Auth wrapper
  [tenant]/
    layout.tsx                ← Tenant: Branding
    dashboard/
      layout.tsx              ← Dashboard: Navigation
      page.tsx

Practical Example: Complete Blog Structure

Blog Layout with Sidebar

A complete blog layout that wraps all blog pages

blog/layout.tsx

Output Preview

Click "Run Code" to see the output

Nested Layout Best Practices

1. Keep Layouts Focused

Each layout should have a single, clear purpose:

TYPESCRIPT
// βœ… Good: Clear purpose
// app/blog/layout.tsx - Adds blog sidebar
// app/dashboard/layout.tsx - Adds dashboard nav

// ❌ Bad: Mixed responsibilities
// app/section/layout.tsx - Sidebar + tabs + modals + forms

2. Organize by Feature, Not Type

PLAINTEXT
// βœ… Good: Organized by feature
app/
  blog/
    layout.tsx
    [slug]/
      page.tsx
  dashboard/
    layout.tsx
    analytics/
      page.tsx

// ❌ Bad: Organized by type
app/
  layouts/
    blog.tsx
    dashboard.tsx
  pages/
    blog/
    dashboard/

3. Extract Shared Components

TYPESCRIPT
// Extract reusable UI into components
// components/Sidebar.tsx
export function Sidebar({ links }) {
  return <aside>{/* sidebar UI */}</aside>;
}

// app/blog/layout.tsx
import { Sidebar } from '@/components/Sidebar';

export default function BlogLayout({ children }) {
  return (
    <div className="flex">
      <Sidebar links={blogLinks} />
      <main>{children}</main>
    </div>
  );
}

4. Consider Mobile First

TYPESCRIPT
export default function Layout({ children }) {
  return (
    <div className="flex flex-col lg:flex-row">
      {/* Sidebar: Full width on mobile, fixed width on desktop */}
      <aside className="w-full lg:w-64">
        Sidebar
      </aside>
      
      {/* Content: Adapts to available space */}
      <main className="flex-1">
        {children}
      </main>
    </div>
  );
}

5. Use Descriptive Names

  • βœ… app/dashboard/layout.tsx - Clear it's for dashboard
  • βœ… app/(marketing)/layout.tsx - Clear it's for marketing
  • ❌ app/layout2.tsx - Unclear purpose
  • ❌ app/section/layout.tsx - Too generic

Debugging Nested Layouts

Visualizing the Layout Tree

Add debug borders to see layout boundaries:

TYPESCRIPT
// Root layout
export default function RootLayout({ children }) {
  return (
    <html>
      <body className="border-4 border-red-500">
        {children}
      </body>
    </html>
  );
}

// Blog layout
export default function BlogLayout({ children }) {
  return (
    <div className="border-4 border-blue-500">
      {children}
    </div>
  );
}

// Page
export default function Page() {
  return (
    <div className="border-4 border-green-500">
      Content
    </div>
  );
}

Checking Which Layouts Render

TYPESCRIPT
export default function Layout({ children }) {
  console.log('πŸ“ BlogLayout rendered');
  return <div>{children}</div>;
}

// Check console to see which layouts render on navigation

Key Takeaways

  • Layouts nest inside layouts - from root to page
  • Each layout receives children - the next layer down
  • Rendering is hierarchical - RootLayout(SectionLayout(Page))
  • State persists across sibling pages - layouts don't re-render
  • Metadata merges/overrides - child overrides parent
  • Can nest indefinitely - as many levels as needed
  • Perfect for section-specific UI - sidebars, tabs, navigation
  • Keep layouts focused - one clear purpose each

What's Next?

You've mastered nested layoutsβ€”a powerful tool for building complex applications! But there's a subtle variant you should know about: templates. While layouts persist across navigation, templates re-render every time.

In the next lesson, we'll explore template.tsx files, understand when to use them instead of layouts, and learn about the important differences in behavior. Templates are less commonly used, but essential for specific scenarios like animations or resetting state.

πŸ—οΈ Layout Architecture Matters

How you structure your layouts significantly impacts your app's maintainability. Take time to plan your layout hierarchyβ€”it's much easier to get it right upfront than to refactor later!

Test Your Understanding

Question 1 of 4

How do nested layouts work in Next.js?

Master nested layouts in Next.js! Learn how to create sophisticated layout hierarchies for complex applications.

Previous
Root Layout and Global Configuration
Next
Templates vs Layouts

Master Next.js Layouts

Join 2,000+ developers building with Next.js. Get the next lesson on templates vs layouts delivered to your inbox - absolutely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

NextJS Tutorials

0 of 70 completed

Your Progress0%

Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

Β© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo