Next.js Cheat Sheet
Quick reference guide for Next.js development
๐ Next.js Quick Reference
This cheat sheet provides quick access to the most commonly used Next.js patterns, commands, and code snippets. Perfect for beginners learning the framework or experienced developers who need a fast reference while coding their applications.
# Quick start
npx create-next-app@latest my-app
cd my-app
npm run dev
Essential Commands
Development
Start development server
npm run dev
# Runs on localhost:3000
Build
Create production build
npm run build
npm run start
Lint
Check code quality
npm run lint
npm run lint -- --fix
Install
Add dependencies
npm install package-name
npm install -D dev-package
๐น File Structure
Next.js uses a file-based routing system where the folder structure in your app directory directly maps to URL routes. Each folder can contain a page.tsx file to create a route, and special files like layout.tsx and loading.tsx add functionality.
my-app/
โโโ app/
โ โโโ layout.tsx # Root layout
โ โโโ page.tsx # Home page (/)
โ โโโ about/
โ โ โโโ page.tsx # About page (/about)
โ โโโ blog/
โ โ โโโ page.tsx # Blog list (/blog)
โ โ โโโ [id]/
โ โ โโโ page.tsx # Blog post (/blog/123)
โ โโโ api/
โ โโโ route.ts # API endpoint (/api)
โโโ components/
โ โโโ Button.tsx # Reusable components
โโโ public/
โ โโโ images/ # Static files
โโโ next.config.js # Configuration
Routes Created:
โ / โ app/page.tsx
โ /about โ app/about/page.tsx
โ /blog โ app/blog/page.tsx
โ /blog/123 โ app/blog/[id]/page.tsx
๐น Page Components
Pages are the main building blocks of your Next.js application. Server Components are the default and can fetch data directly, while Client Components handle interactivity. Use the appropriate type based on your needs for optimal performance.
๐ธ Server Component (Default)
// app/page.tsx
export default function Page() {
return (
<div>
<h1>Home Page</h1>
<p>This is a server component</p>
</div>
)
}
๐ธ Client Component
// app/counter/page.tsx
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
)
}
๐ธ Dynamic Route
// app/blog/[id]/page.tsx
export default function BlogPost({ params }) {
return <h1>Post ID: {params.id}</h1>
}
๐น Data Fetching
Next.js provides multiple ways to fetch data depending on your needs. Server Components can fetch data directly using async/await, while Client Components use hooks like useEffect or libraries like SWR for client-side data fetching and caching.
๐ธ Server Component Fetch
// app/posts/page.tsx
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
cache: 'no-store' // Dynamic data
})
return res.json()
}
export default async function Posts() {
const posts = await getPosts()
return (
<div>
{posts.map(post => (
<div key={post.id}>{post.title}</div>
))}
</div>
)
}
๐ธ Client Component Fetch
'use client'
import { useState, useEffect } from 'react'
export default function Posts() {
const [posts, setPosts] = useState([])
useEffect(() => {
fetch('https://api.example.com/posts')
.then(res => res.json())
.then(data => setPosts(data))
}, [])
return (
<div>
{posts.map(post => (
<div key={post.id}>{post.title}</div>
))}
</div>
)
}
๐ธ Cache Options
// Force cache (default)
fetch(url, { cache: 'force-cache' })
// No cache (always fresh)
fetch(url, { cache: 'no-store' })
// Revalidate every 60 seconds
fetch(url, { next: { revalidate: 60 } })
๐น Navigation
Next.js provides the Link component for client-side navigation between pages and the useRouter hook for programmatic navigation. These tools enable fast page transitions without full page reloads, creating a smooth single-page application experience.
๐ธ Link Component
import Link from 'next/link'
export default function Nav() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/blog/123">Blog Post</Link>
</nav>
)
}
๐ธ useRouter Hook
'use client'
import { useRouter } from 'next/navigation'
export default function Button() {
const router = useRouter()
return (
<button onClick={() => router.push('/dashboard')}>
Go to Dashboard
</button>
)
}
๐ธ Navigation Methods
router.push('/path') // Navigate to path
router.replace('/path') // Replace current history
router.back() // Go back
router.forward() // Go forward
router.refresh() // Refresh current route
๐น Layouts
Layouts wrap multiple pages and persist across navigation, perfect for shared UI elements like headers and footers. They prevent unnecessary re-renders and maintain state. Root layout is required and wraps your entire application with HTML structure.
// app/layout.tsx (Root Layout - Required)
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<header>My App</header>
{children}
<footer>ยฉ 2025</footer>
</body>
</html>
)
}
// app/dashboard/layout.tsx (Nested Layout)
export default function DashboardLayout({ children }) {
return (
<div>
<aside>Sidebar</aside>
<main>{children}</main>
</div>
)
}
Result:
โ Header and footer on all pages
โ Dashboard pages get sidebar
โ Layouts don't re-render on navigation
๐น API Routes
API routes let you build backend endpoints directly in your Next.js application. Create route.ts files to handle HTTP requests with functions named after HTTP methods. Perfect for building APIs, webhooks, and server-side logic without a separate backend.
// app/api/users/route.ts
import { NextResponse } from 'next/server'
// GET request
export async function GET() {
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
]
return NextResponse.json(users)
}
// POST request
export async function POST(request: Request) {
const body = await request.json()
// Save to database
return NextResponse.json({
success: true,
data: body
})
}
// Dynamic route: app/api/users/[id]/route.ts
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const user = { id: params.id, name: 'John' }
return NextResponse.json(user)
}
Endpoints Created:
โ GET /api/users โ List all users
โ POST /api/users โ Create user
โ GET /api/users/123 โ Get user by ID
๐น Metadata
Metadata improves SEO and social sharing by defining page titles, descriptions, and Open Graph tags. Export a metadata object from any page or layout to set static metadata, or use generateMetadata function for dynamic metadata based on page parameters.
// app/page.tsx - Static Metadata
export const metadata = {
title: 'My App',
description: 'Welcome to my app',
openGraph: {
title: 'My App',
description: 'Welcome to my app',
images: ['/og-image.jpg'],
},
}
// app/blog/[id]/page.tsx - Dynamic Metadata
export async function generateMetadata({ params }) {
const post = await getPost(params.id)
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
images: [post.image],
},
}
}
Result:
โ SEO-friendly page titles
โ Social media preview cards
โ Dynamic metadata per page
๐น Environment Variables
Environment variables store sensitive data and configuration settings outside your code. Create a .env.local file for local development. Use NEXT_PUBLIC_ prefix for variables that need to be accessible in the browser, otherwise they're server-only for security.
# .env.local
DATABASE_URL=postgresql://... # Server-side only
API_SECRET=abc123 # Server-side only
NEXT_PUBLIC_API_URL=https://api.com # Available in browser
NEXT_PUBLIC_SITE_NAME=My App # Available in browser
Usage:
// Server Component - Access all variables
export default function Page() {
const dbUrl = process.env.DATABASE_URL
const apiUrl = process.env.NEXT_PUBLIC_API_URL
return <div>{apiUrl}</div>
}
// Client Component - Only NEXT_PUBLIC_ variables
'use client'
export default function Page() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL
return <div>{apiUrl}</div>
}
Result:
โ Secrets kept secure on server
โ Public config available in browser
โ Easy environment management