Layouts

Layouts wrap your pages with shared UI elements like headers, footers, and navigation.

Creating a Layout

Create _layout.jsx in any folder to wrap all routes in that folder:

plaintext
src/client/routes/ ├── _layout.jsx ← Wraps all routes ├── index.jsx ├── about.jsx └── dashboard/ ├── _layout.jsx ← Wraps only /dashboard/* routes ├── index.jsx └── settings.jsx

Basic Layout

Use <Outlet /> to render child routes:

jsx
// src/client/routes/_layout.jsx import { Link, Outlet } from 'react-router'; export default function RootLayout() { return ( <div> <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> </nav> <main> <Outlet /> {/* Child routes render here */} </main> <footer> © 2024 My App </footer> </div> ); }

Nested Layouts

Layouts can be nested for different sections:

jsx
// src/client/routes/dashboard/_layout.jsx import { Outlet, Link } from 'react-router'; export default function DashboardLayout() { return ( <div className="flex"> <aside className="w-64 bg-gray-900 p-4"> <nav> <Link to="/dashboard">Overview</Link> <Link to="/dashboard/settings">Settings</Link> <Link to="/dashboard/profile">Profile</Link> </nav> </aside> <main className="flex-1"> <Outlet /> {/* Child routes render here */} </main> </div> ); }

Result: /dashboard has both root layout AND dashboard layout.
Nested: Navbar → Sidebar → Page content → Footer

Layout Hierarchy

plaintext
_layout.jsx (root) └─ Navbar └─ <Outlet> └─ dashboard/_layout.jsx └─ Sidebar └─ <Outlet> └─ dashboard/settings.jsx (your page) └─ Footer

Conditional Layouts

Skip layouts for specific routes by creating them outside the layout folder:

plaintext
src/client/routes/ ├── _layout.jsx ← Most pages use this ├── login.jsx ← No layout (standalone) ├── register.jsx ← No layout (standalone) └── dashboard/ ├── _layout.jsx ← Dashboard pages use this └── index.jsx

Shared Layout State

Pass data through layouts using React Context:

jsx
// src/client/context/ThemeContext.jsx import { createContext, useContext, useState } from 'react'; export const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { return useContext(ThemeContext); }

Use in layout:

jsx
// src/client/routes/_layout.jsx import { Outlet } from 'react-router'; import { ThemeProvider, useTheme } from '../context/ThemeContext'; export default function RootLayout() { return ( <ThemeProvider> <LayoutContent /> </ThemeProvider> ); } function LayoutContent() { const { theme, setTheme } = useTheme(); return ( <div className={theme === 'dark' ? 'dark' : ''}> <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle Theme </button> <Outlet /> </div> ); }