The App Router uses files and folders under app/ to define routes, layouts, loading states and error boundaries.
text
app/
├── layout.tsx
├── page.tsx
├── about/
│ └── page.tsx
└── products/
├── page.tsx
└── [id]/
└── page.tsxThis produces the following route structure:
| File | URL |
|---|---|
app/page.tsx | / |
app/about/page.tsx | /about |
app/products/page.tsx | /products |
app/products/[id]/page.tsx | /products/123 for an ID of 123 |
Folders organize the URL structure, while special files define what happens at those routes.
In the App Router, pages and layouts are Server Components by default.
Server Components are useful for:
Client Components are useful for:
onClick.localStorage.Example:
tsx
// app/components/Counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}The "use client" directive defines a client module boundary. It should be placed before imports.
It does not mean the component can never contribute to server-generated HTML: Client Components can be prerendered on the server and then hydrated in the browser.
Common framework features include:
next/image for image handling and optimization.next/font for font management.next/script for controlling script loading.Link component.Each feature has its own configuration and limitations, which we’ll cover in Module 05 and Module 10.
A Next.js project can combine several layers:
Presentation: pages, layouts and UI components
Application logic: Server Components, Server Actions and Route Handlers
Data layer: database, ORM and external services
These are logical layers, not strict physical boundaries. For example, a Server Component can call a database library directly, while an external mobile client might call a Route Handler.
Security rule: Server-side code is not automatically safe. You must still validate input, enforce authorization and avoid exposing secrets or sensitive data.