Nested Routes and Layouts in Next.js¶
In Next.js's App Router, layout.tsx files are not just for the root of your application. You can nest them to create more complex UI structures that share components across specific groups of routes. This is incredibly powerful for maintaining consistent layouts within different sections of your application, like a dashboard, an admin panel, or a user profile area.
Sharing UI Across Routes with layout.tsx Files¶
A layout.tsx file (or layout.js for JavaScript) defines UI that is shared across multiple pages within a particular route segment. When you create a layout.tsx inside a folder, all page.tsx files (and any nested layout.tsx files) within that folder and its subfolders will inherit that layout.
The core idea is that a layout component receives a children prop, which represents the content of the nested route segment.
Think of it like this:
app/
├── layout.tsx // Root layout (e.g., Header, Footer)
└── dashboard/
├── layout.tsx // Dashboard layout (e.g., Dashboard Sidebar, Nav)
└── page.tsx // Dashboard content
In this structure:
- The
dashboard/page.tsxcontent will be rendered insidedashboard/layout.tsx. - The
dashboard/layout.tsx(along with thedashboard/page.tsxcontent) will then be rendered inside theapp/layout.tsx.
This creates a hierarchical layout structure where UI elements are reused efficiently.
Creating a Dashboard Layout for Authenticated Users (/dashboard/layout.tsx)¶
For our Task Management App, we want a different layout for the dashboard section. The dashboard will likely have a sidebar with navigation specific to tasks, user profiles, or settings, which shouldn't appear on the public homepage.
Let's create a specific layout for our /dashboard route.
-
Create a new file named
layout.tsxinside yourapp/dashboard/folder:my-task-app/ └── app/ ├── layout.tsx ├── page.tsx └── dashboard/ ├── layout.tsx <-- NEW FILE └── page.tsx └── globals.css -
Add the following content to
app/dashboard/layout.tsx:app/dashboard/layout.tsx// app/dashboard/layout.tsx // This layout specifically applies to the /dashboard route and any of its nested routes. // It is a Server Component by default. export default function DashboardLayout({ children, // The content of the nested page (e.g., app/dashboard/page.tsx) }: { children: React.ReactNode; // TypeScript type for children prop }) { return ( <div className="flex flex-col md:flex-row min-h-[calc(100vh-180px)]"> {/* Adjusted min-height for better fit with root header/footer */} {/* Dashboard Sidebar */} <aside className="w-full md:w-64 bg-gray-50 p-6 shadow-md rounded-lg md:mr-6 mb-6 md:mb-0"> <h3 className="text-xl font-semibold text-gray-700 mb-4">Dashboard Navigation</h3> <nav> <ul className="space-y-3"> <li> <a href="/dashboard" // Using a simple href for now, will use <Link> later className="block p-3 rounded-md text-blue-600 hover:bg-blue-100 transition duration-200" > All Tasks </a> </li> <li> <a href="/dashboard/settings" // Example for future nested route className="block p-3 rounded-md text-gray-700 hover:bg-gray-200 transition duration-200" > Settings </a> </li> {/* More navigation items will be added here */} </ul> </nav> </aside> {/* Main content area for the dashboard */} <section className="flex-grow bg-white p-6 shadow-md rounded-lg"> {children} {/* This is where app/dashboard/page.tsx (or other nested pages) will render */} </section> </div> ); }
Summary¶
What we've done:
- We've introduced a
layout.tsxfile inside theapp/dashboarddirectory. - This
DashboardLayoutcomponent now provides a common UI structure (a sidebar and a main content area) for all routes starting with/dashboard. - The
childrenprop withinDashboardLayoutensures that thepage.tsxfile (likeapp/dashboard/page.tsx) or any further nested routes within/dashboardwill be rendered inside this layout. - We've used basic Tailwind CSS classes to style the sidebar and main section.
To observe the nested layout:
- Ensure your development server is still running (
npm run dev). - Open your browser and navigate to
http://localhost:3000/dashboard.
You should now see your dashboard page with a distinct sidebar on the left and your "Your Dashboard" message in the main content area, all within the global header and footer. This clearly demonstrates how nested layouts provide a powerful way to manage shared UI segments in your Next.js application.
In the next section, we'll explore Dynamic Routes, which will allow us to create pages for individual tasks based on their unique IDs.