The app/ Directory

Folders inside app/ become URL segments, and special filenames like page.tsx and layout.tsx give them meaning.

Syntaxapp/<segment>/page.tsx

The 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.

The app directory maps folders to URL routes app/ → becomes your URL routes app/ layout.tsx page.tsx about/ page.tsx blog/ page.tsx [slug]/ page.tsx / /about /blog /blog/hello-world folder = route segment, page.tsx = the page
Folders inside app/ define the URL; a page.tsx makes a segment publicly routable.

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

Example · typescript
// 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.

Example · ts
// 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.

Example · ts
// 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.

Example · ts
// app/dashboard/loading.tsx
export default function Loading() {
  return <p>Loading dashboard...</p>;
}

Discussion

  • Be the first to comment on this lesson.