963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
142 lines
3.7 KiB
Markdown
142 lines
3.7 KiB
Markdown
# File Conventions
|
|
|
|
Next.js App Router uses file-based routing with special file conventions.
|
|
|
|
## Project Structure
|
|
|
|
Reference: https://nextjs.org/docs/app/getting-started/project-structure
|
|
|
|
```
|
|
app/
|
|
├── layout.tsx # Root layout (required)
|
|
├── page.tsx # Home page (/)
|
|
├── loading.tsx # Loading UI
|
|
├── error.tsx # Error UI
|
|
├── not-found.tsx # 404 UI
|
|
├── global-error.tsx # Global error UI
|
|
├── route.ts # API endpoint
|
|
├── template.tsx # Re-rendered layout
|
|
├── default.tsx # Parallel route fallback
|
|
├── blog/
|
|
│ ├── page.tsx # /blog
|
|
│ └── [slug]/
|
|
│ └── page.tsx # /blog/:slug
|
|
└── (group)/ # Route group (no URL impact)
|
|
└── page.tsx
|
|
```
|
|
|
|
## Special Files
|
|
|
|
| File | Purpose |
|
|
| --------------- | ---------------------------------------- |
|
|
| `page.tsx` | UI for a route segment |
|
|
| `layout.tsx` | Shared UI for segment and children |
|
|
| `loading.tsx` | Loading UI (Suspense boundary) |
|
|
| `error.tsx` | Error UI (Error boundary) |
|
|
| `not-found.tsx` | 404 UI |
|
|
| `route.ts` | API endpoint |
|
|
| `template.tsx` | Like layout but re-renders on navigation |
|
|
| `default.tsx` | Fallback for parallel routes |
|
|
|
|
## Route Segments
|
|
|
|
```
|
|
app/
|
|
├── blog/ # Static segment: /blog
|
|
├── [slug]/ # Dynamic segment: /:slug
|
|
├── [...slug]/ # Catch-all: /a/b/c
|
|
├── [[...slug]]/ # Optional catch-all: / or /a/b/c
|
|
└── (marketing)/ # Route group (ignored in URL)
|
|
```
|
|
|
|
## Parallel Routes
|
|
|
|
```
|
|
app/
|
|
├── @analytics/
|
|
│ └── page.tsx
|
|
├── @sidebar/
|
|
│ └── page.tsx
|
|
└── layout.tsx # Receives { analytics, sidebar } as props
|
|
```
|
|
|
|
## Intercepting Routes
|
|
|
|
```
|
|
app/
|
|
├── feed/
|
|
│ └── page.tsx
|
|
├── @modal/
|
|
│ └── (.)photo/[id]/ # Intercepts /photo/[id] from /feed
|
|
│ └── page.tsx
|
|
└── photo/[id]/
|
|
└── page.tsx
|
|
```
|
|
|
|
Conventions:
|
|
|
|
- `(.)` - same level
|
|
- `(..)` - one level up
|
|
- `(..)(..)` - two levels up
|
|
- `(...)` - from root
|
|
|
|
## Private Folders
|
|
|
|
```
|
|
app/
|
|
├── _components/ # Private folder (not a route)
|
|
│ └── Button.tsx
|
|
└── page.tsx
|
|
```
|
|
|
|
Prefix with `_` to exclude from routing.
|
|
|
|
## Middleware / Proxy
|
|
|
|
### Next.js 14-15: `middleware.ts`
|
|
|
|
```ts
|
|
// middleware.ts (root of project)
|
|
import { NextResponse } from 'next/server';
|
|
import type { NextRequest } from 'next/server';
|
|
|
|
export function middleware(request: NextRequest) {
|
|
// Auth, redirects, rewrites, etc.
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ['/dashboard/:path*', '/api/:path*'],
|
|
};
|
|
```
|
|
|
|
### Next.js 16+: `proxy.ts`
|
|
|
|
Renamed for clarity - same capabilities, different names:
|
|
|
|
```ts
|
|
// proxy.ts (root of project)
|
|
import { NextResponse } from 'next/server';
|
|
import type { NextRequest } from 'next/server';
|
|
|
|
export function proxy(request: NextRequest) {
|
|
// Same logic as middleware
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const proxyConfig = {
|
|
matcher: ['/dashboard/:path*', '/api/:path*'],
|
|
};
|
|
```
|
|
|
|
| Version | File | Export | Config |
|
|
| ------- | --------------- | -------------- | ------------- |
|
|
| v14-15 | `middleware.ts` | `middleware()` | `config` |
|
|
| v16+ | `proxy.ts` | `proxy()` | `proxyConfig` |
|
|
|
|
**Migration**: Run `npx @next/codemod@latest upgrade` to auto-rename.
|
|
|
|
## File Conventions Reference
|
|
|
|
Reference: https://nextjs.org/docs/app/api-reference/file-conventions
|