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

๐Ÿง  Test Your Knowledge

Which command starts the Next.js development server?