Applies to Next.js 13+ with the App Router. The App Router uses app/ for routing; the legacy pages/ directory still works but is optional.
Recommended Structure
my-next-app/
├── app/ # App Router — routing only
│ ├── layout.tsx # Root layout (header, footer, providers)
│ ├── page.tsx # Home route (/)
│ ├── about/
│ │ └── page.tsx # /about route
│ ├── blog/
│ │ ├── page.tsx # /blog route
│ │ └── [id]/
│ │ └── page.tsx # /blog/:id (dynamic route)
│ └── api/
│ └── hello/
│ └── route.ts # Route Handler: GET /api/hello
│
├── src/
│ ├── components/ # Reusable UI components
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Utilities, helpers, API clients
│ ├── services/ # External API integrations
│ ├── types/ # Shared TypeScript types
│ └── styles/ # Global styles or theme
│
├── public/ # Static assets (served at /)
├── .env.local # Local env variables (gitignored)
├── next.config.ts # Supports TypeScript since Next.js 15
├── tsconfig.json
└── package.json
Key Rules
app/ is for routing only. Don't put components, hooks, or utilities inside app/. Use src/ for all non-route code — keeps app/ readable as a pure route map.
Parenthesized folders are route groups. app/(marketing)/ groups routes without affecting the URL — the segment won't appear in the path. Don't use parentheses for non-routing purposes (components, styles, lib) — it's misleading.
API routes: Use app/api/<route>/route.ts (Route Handlers). The pages/api/ approach still works but mixing both routing paradigms in one app causes confusion — pick one.
Use src/ for any non-trivial project. Keeps the root clean (config files only at root).
Component Organization (Larger Apps)
src/components/
├── ui/ # Generic atoms — Button, Input, Modal
├── layout/ # Structural — Navbar, Sidebar, Footer
└── features/ # Feature-scoped — UserCard, BlogPost
app/ Special Files
| File | Purpose |
|---|---|
layout.tsx | Persistent wrapper for a route segment and its children |
page.tsx | The route's unique UI — makes the route publicly accessible |
loading.tsx | Suspense boundary shown while the segment loads |
error.tsx | Error boundary UI for the segment |
not-found.tsx | 404 UI for the segment |
route.ts | API Route Handler (no UI rendered) |