Next.js Cheatsheet
A dense, scannable reference for the file conventions, routing patterns, and code snippets used constantly in App Router development.
File conventions
File | Purpose |
|---|---|
| Makes a route segment publicly reachable and defines its UI |
| Shared UI that wraps a segment and its children; preserved across navigations |
| Instant loading UI shown via Suspense while a segment loads |
| Client Component error boundary UI for a segment |
| UI shown when |
| A Route Handler — defines |
| Runs before requests complete routing, at the project root |
| Like |
| Sidebar/source-of-truth list of slugs and labels for a topic |
Routing patterns
Folder name | Matches |
|---|---|
|
|
|
|
|
|
|
|
|
|
| A named parallel slot, rendered alongside |
| Intercepts |
Data fetching
Fetch in a Server Component
export default async function Page() {
const res = await fetch('https://api.example.com/items', {
next: { revalidate: 60 }, // ISR: revalidate at most every 60s
})
const items = await res.json()
return <ul>{items.map((i) => <li key={i.id}>{i.name}</li>)}</ul>
}Static params for a dynamic route
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map((post) => ({ slug: post.slug }))
}Server Actions
A minimal form-bound Server Action
// app/actions.ts
'use server'
export async function createItem(formData: FormData) {
const name = formData.get('name')
// ...save to database...
}
// app/page.tsx
import { createItem } from './actions'
export default function Page() {
return (
<form action={createItem}>
<input name="name" />
<button type="submit">Add</button>
</form>
)
}Metadata
Static and dynamic metadata
// Static
export const metadata = {
title: 'My Page',
description: 'A page description',
}
// Dynamic
export async function generateMetadata({ params }) {
const { slug } = await params
const post = await getPost(slug)
return { title: post.title, description: post.excerpt }
}next/image, next/font, next/link
Core built-in primitives
import Image from 'next/image'
import Link from 'next/link'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function Page() {
return (
<main className={inter.className}>
<Link href="/about">About</Link>
<Image src="/hero.png" alt="Hero" width={800} height={400} priority />
</main>
)
}Middleware
middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const isLoggedIn = request.cookies.has('session')
if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/dashboard/:path*'],
}