Layouts & pages
Pages and layouts are just React components. The framework wraps your page with the nearest layout chain and renders the result.
A page
The simplest page is a default-exported component. It receives params and searchParams as props.
export default function HomePage() {
return <h1>Hello, world</h1>;
}A layout
A layout wraps one or more pages. It receives children as a prop. The root layout (in app/layout.tsx) is required and must render <html> and <body>.
import type { ReactNode } from "react";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}Nested layouts
Add a layout.tsx to any segment to wrap that segment and its children. Layouts are composed — they don't replace parent layouts.
import type { ReactNode } from "react";
import { Sidebar } from "@/components/sidebar";
export default function DashboardLayout({ children }: { children: ReactNode }) {
return (
<div className="grid grid-cols-[14rem_1fr]">
<Sidebar />
<main>{children}</main>
</div>
);
}Loading states
Export a loading.tsx to show a UI while the page is being prepared. In ssr mode, the framework will show this until the page is fully rendered.
export default function Loading() {
return <div className="animate-pulse">Loading dashboard…</div>;
}Error boundaries
Export an error.tsx to catch errors thrown by this segment and its children.
"use client";
export default function ErrorBoundary({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h2>Something went wrong</h2>
<p>{error.message}</p>
<button onClick={reset}>Try again</button>
</div>
);
}Not found
A not-found.tsx is rendered when no route matches. The closest one in the tree is used.
Next steps
Continue to Data fetching.