Skip to content

Next.js Cheatsheet — Complete Quick Reference (2026)

DodaTech Updated 2026-06-20 3 min read

In this tutorial, you'll learn about Next.js Cheatsheet. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Next.js is a React framework providing file-based routing, server-side rendering, static generation, API routes, and middleware — supporting both Pages Router and App Router.

// app/page.tsx — route: /
export default function Home() {
  return <h1>Home</h1>
}

// app/blog/[slug]/page.tsx — route: /blog/hello-world
export default async function Page({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)
  return <article>{post.title}</article>
}

// app/layout.tsx — shared layout
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <nav>Header</nav>
        {children}
        <footer>Footer</footer>
      </body>
    </html>
  )
}

Server vs Client Components

// app/page.tsx — Server Component (default)
// Can: async/await, access DB, read files, keep secrets
// Cannot: useState, useEffect, event handlers
const data = await db.query()

// app/counter.tsx — Client Component
'use client'
import { useState } from 'react'
export default function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}

Data Fetching (App Router)

// Server-side fetch (cached by default)
async function getPost(slug: string) {
  const res = await fetch(`https://api.example.com/posts/${slug}`)
  return res.json()
}

// Revalidate (ISR)
export const revalidate = 3600    // revalidate every hour

// Dynamic rendering
export const dynamic = 'force-dynamic'

// Parallel data fetching
const [posts, users] = await Promise.all([getPosts(), getUsers()])

Pages Router

// pages/index.tsx
export default function Home() { return <h1>Home</h1> }

// pages/blog/[slug].tsx
export async function getStaticPaths() {
  const posts = await fetchPosts()
  return { paths: posts.map(p => ({ params: { slug: p.slug } })), fallback: false }
}
export async function getStaticProps({ params }) {
  const post = await getPost(params.slug)
  return { props: { post }, revalidate: 3600 }
}

API Routes

// app/api/hello/route.ts (App Router)
export async function GET() {
  return Response.json({ message: "hello" })
}
export async function POST(req: Request) {
  const body = await req.json()
  return Response.json({ received: body })
}

// pages/api/hello.ts (Pages Router)
export default function handler(req, res) {
  res.status(200).json({ message: "hello" })
}

Middleware

// middleware.ts
export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')
  if (!token) return NextResponse.redirect(new URL('/login', request.url))
  return NextResponse.next()
}
export const config = { matcher: ['/dashboard/:path*'] }

Route Handlers & Search Params

// app/search/page.tsx
import { useSearchParams } from 'next/navigation'
// or on server:
export default async function Page({ searchParams }: { searchParams: { q: string } }) {
  return <div>Search: {searchParams.q}</div>
}

Image & Font Optimizations

import Image from 'next/image'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

<Image src="/hero.webp" alt="hero" width={1200} height={600} priority />
<html className={inter.className}>

Deployment

# Build
npm run build        # outputs .next folder
pnpm run build

# Standalone output (docker-friendly)
# next.config.js: { output: 'standalone' }
# Output: .next/standalone/ — includes minimal node_modules

# Environment variables
NEXT_PUBLIC_API_URL=https://api.example.com  # public (inlined at build)
DB_PASSWORD=secret                            # server-only

Must-Know Items

  • Server Components are the default in App Router — use 'use client' only when you need interactivity
  • fetch() is extended with Caching: { cache: 'force-cache' } (default), { cache: 'no-store' }, { next: { revalidate: 60 } }
  • Layouts persist across navigations and do not re-render; pages re-render per route
  • loading.tsx shows a fallback UI during page load (App Router)
  • error.tsx catches errors in the page subtree (App Router)
  • not-found.tsx handles 404s per route segment
  • Route groups (marketing) and (dashboard) organize without affecting URL
  • Parallel routes @analytics render multiple pages in the same layout slot

{{< faq "What is the difference between Server Components and Client Components in Next.js?">}}Server Components render on the server, can directly access databases and file systems, keep secrets secure, and reduce client JS. Client Components ('use client') render on the client, support hooks (useState, useEffect), and handle interactivity. Default to Server Components; use Client only when you need browser APIs.{{< /faq >}}

How does caching work with fetch() in Next.js App Router?

By default, fetch() results are cached (equivalent to force-cache). Use { cache: 'no-store' } for fresh data per request, or { next: { revalidate: 60 } } for ISR (time-based revalidation). fetch() calls are automatically deduplicated within the same request scope.

See full Next.js tutorials for full-stack React development.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro