The app/ Directory
Folders inside app/ become URL segments, and special filenames like page.tsx and layout.tsx give them meaning.
Syntax
app/<segment>/page.tsxThe App Router is file-system based: the folder structure inside app/ directly maps to your URLs. A folder creates a route segment, and special files inside it define what that segment renders.
Special filenames
page.tsx— makes a route publicly accessible and renders its UI.layout.tsx— shared UI that wraps a segment and its children.loading.tsx— instant loading state (Suspense fallback).error.tsx— error boundary for the segment.not-found.tsx— UI for missing content.
A folder without a page.tsx is not routable — it just groups files.
Example
// app/about/page.tsx -> served at /about
export default function AboutPage() {
return <h1>About us</h1>;
}When to use it
- A developer creates app/blog/[slug]/page.tsx to handle dynamic post URLs without manual route registration.
- A team adds app/dashboard/layout.tsx to share a sidebar across all dashboard sub-pages without duplicating markup.
- A product page gets a loading.tsx file so Next.js shows a skeleton while the server component fetches data.
More examples
Root layout for all pages
layout.tsx is rendered once and wraps every child page in that segment, ideal for nav and providers.
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}Nested dashboard layout
Adding layout.tsx inside a sub-folder creates a nested shell that only applies to dashboard routes.
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="dashboard-shell">
<aside>Sidebar</aside>
<main>{children}</main>
</div>
);
}Automatic loading state
Next.js automatically streams this component while the async page.tsx above it resolves on the server.
// app/dashboard/loading.tsx
export default function Loading() {
return <p>Loading dashboard...</p>;
}
Discussion