Skip to content
Next.js Reference & Cheatsheet

Next.js Reference & Cheatsheet

DodaTech Updated Jun 6, 2026 10 min read

Next.js Reference & Cheatsheet

Next.js is a React framework for production-ready web applications, providing file-based routing, multiple data-fetching strategies (SSR, SSG, ISR), API routes, and middleware — all built on top of React.

What You’ll Learn

  • How Next.js file-based routing works in both Pages Router and App Router
  • The difference between SSR, SSG, and ISR and when to use each
  • How to create API routes and middleware for backend logic
  • How to use Next.js built-in components like Image and Link
  • How to handle authentication and redirects with middleware

Why Next.js Matters

Next.js powers some of the largest websites in the world, handling millions of requests per day. Companies choose Next.js because it solves real problems: slow page loads (with SSG/ISR), poor SEO (with SSR), and complex routing. The same patterns you learn here power tools like Durga Antivirus Pro dashboards that need both fast static pages and real-time security data, and Doda Browser extensions that fetch and display dynamic content efficiently.

    flowchart LR
    A[React Basics] --> B[Next.js Fundamentals]
    B --> C[Pages Router]
    B --> D[App Router]
    C --> E[SSR / SSG / ISR]
    D --> E
    E --> F[API Routes & Middleware]
    F --> G[Full-Stack Next.js Apps]
    style B fill:#4a90d9,color:#fff
  
Prerequisites: You should know React (components, props, hooks) and basic JavaScript. Familiarity with Node.js helps but is not required.

File-Based Routing — Pages Router (Classic)

Think of file-based routing like organizing files in a folder. Each file in the pages/ folder automatically becomes a URL route. This is the Pages Router, the original Next.js routing system.

pages/
├── index.js          → /
├── about.js          → /about
├── blog/
│   ├── index.js      → /blog
│   └── [slug].js     → /blog/:slug
├── api/
│   └── users.js      → /api/users
└── 404.js            → custom 404

How it works: The file pages/blog/[slug].js creates a dynamic route. The [slug] part is a parameter — whatever the user types after /blog/ becomes available in your component. For example, visiting /blog/hello-world gives you slug = "hello-world".

File-Based Routing — App Router (Next.js 13+)

The App Router is the modern way to build Next.js apps. Instead of separate files for pages and layouts, you use a single app/ folder with special file names:

app/
├── page.js           → /
├── layout.js         → root layout
├── about/
│   └── page.js       → /about
├── blog/
│   ├── page.js       → /blog
│   └── [slug]/
│       └── page.js   → /blog/:slug
└── api/
    └── route.js      → /api

Why App Router? It supports server components by default, which means less JavaScript sent to the browser. Every component in app/ is a server component unless you add "use client" at the top. Server components can fetch data directly without useEffect or state management.

Data Fetching Methods

Next.js offers three main strategies for getting data into your pages. Choosing the right one depends on when you want the data to load.

getStaticProps — Static Site Generation (SSG)

Data is fetched at build time — once, when you deploy. The HTML page is pre-built and served instantly.

export async function getStaticProps() {
  // This runs at build time, not on every request
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  return {
    props: { posts },
    revalidate: 60 // ISR: re-generate at most every 60 seconds
  };
}

Line by line: getStaticProps is an async function that Next.js calls during build. We fetch data from an API, parse it to JSON, and return it as props. The revalidate: 60 option enables Incremental Static Regeneration (ISR) — Next.js will re-fetch the data at most every 60 seconds, so your static page stays fresh.

Best for: Blog posts, marketing pages, documentation — content that doesn’t change frequently.

getServerSideProps — Server-Side Rendering (SSR)

Data is fetched on every request — the user waits while the server gets the data and renders the HTML.

export async function getServerSideProps(context) {
  // context gives us access to params, query, req, res
  const { params, req, query } = context;
  const res = await fetch(`https://api.example.com/post/${params.slug}`);
  const post = await res.json();

  return { props: { post } };
}

Line by line: context contains the request information. params.slug comes from the URL (the [slug] in the filename). We fetch fresh data using that slug, parse it, and return it. Unlike getStaticProps, this runs on every visit.

Best for: User dashboards, real-time data, pages that need authentication — content that changes often.

getStaticPaths

When using getStaticProps with dynamic routes, you also need getStaticPaths to tell Next.js which paths to pre-build:

export async function getStaticPaths() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  return {
    paths: posts.map(p => ({ params: { slug: p.slug } })),
    fallback: "blocking"
    // "blocking": new paths are generated on first visit
    // false: only pre-built paths work (404 for others)
    // true: show fallback UI while generating
  };
}

Line by line: We fetch all posts, then map each one to a path object. fallback: "blocking" means if someone visits a path we didn’t pre-build, Next.js will generate it on-the-fly (the user waits briefly, but then it’s cached).

Server Components (App Router)

In the App Router, every component is a server component by default. This is a major shift from traditional React.

// app/page.js — Server Component by default
async function Page() {
  // We can use async/await directly — no useEffect needed!
  const res = await fetch("https://api.example.com/data");
  const posts = await res.json();

  return (
    <div>
      {posts.map(p => <Post key={p.id} {...p} />)}
    </div>
  );
}

Why this matters: In traditional React, you’d use useEffect to fetch data, which means a loading state, extra JavaScript, and slower page loads. With server components, the fetching happens on the server, so the user gets fully-rendered HTML with no client-side loading spinners.

API Routes

Next.js lets you build backend endpoints directly in your app — no separate server needed.

// pages/api/users.js — or app/api/users/route.js in App Router
export default async function handler(req, res) {
  // req.method tells us what HTTP verb was used (GET, POST, etc.)
  if (req.method === "GET") {
    const users = await db.findMany();
    res.status(200).json(users);
  } else if (req.method === "POST") {
    const user = await db.create(req.body);
    res.status(201).json(user);
  } else {
    res.status(405).json({ error: "Method not allowed" });
  }
}

Line by line: The handler function receives the HTTP request and response. We check the method, then respond accordingly. res.status(200).json(users) sends a JSON response with a 200 (OK) status. For POST, we create a new record and return 201 (Created).

Best for: Form submissions, authentication endpoints, webhook handlers — any server-side logic your frontend needs.

Middleware

Middleware runs before a request reaches your page. Think of it as a guard at the door — it checks who’s coming in and decides whether to let them through.

// middleware.js (lives in the root of your project)
export function middleware(request) {
  // Read the token cookie — this is where authentication happens
  const token = request.cookies.get("token");

  // If no token and trying to access /admin, redirect to login
  if (!token && request.nextUrl.pathname.startsWith("/admin")) {
    return Response.redirect(new URL("/login", request.url));
  }

  // Otherwise, let the request through
}

export const config = {
  matcher: ["/admin/:path*"] // Only run on /admin paths
};

Line by line: The middleware checks for a cookie named “token”. If it’s missing and the user is visiting an admin page, we redirect to /login. The config.matcher tells Next.js which paths should trigger this middleware — this prevents it from running on every single request.

Built-in Components

Next.js provides optimized components that replace standard HTML elements:

import Image from "next/image";
import Link from "next/link";
import Head from "next/head";

// Image: automatic optimization, lazy loading, responsive
<Image
  src="/hero.jpg"
  alt="Hero banner"
  width={1200}
  height={600}
  priority // Skip lazy loading  load immediately
/>

// Link: client-side navigation (no full page reload)
<Link href="/about">About Us</Link>

// Head: set page title and meta tags
<Head>
  <title>My Next.js Page</title>
</Head>

Why Image matters: A standard <img> tag loads images at full size, slowing down your page. Next.js Image component automatically serves responsive sizes, converts to WebP, and lazy-loads images below the fold. This is the kind of optimization that tools like DodaZIP apply to file compression — smaller output, same quality.


Common Mistakes

  1. Forgetting getStaticPaths with dynamic SSG routes: If you use getStaticProps on a dynamic page like [slug].js, you MUST also export getStaticPaths. Without it, Next.js doesn’t know which pages to build.

  2. Using getServerSideProps when SSG would work: Every SSR request hits your server and database. If your data changes once an hour, use ISR instead — your users (and your server) will thank you.

  3. Not handling fallback correctly: Setting fallback: false means any unlisted path returns 404. For large sites with thousands of pages, use fallback: "blocking" so new pages are generated on demand.

  4. Putting "use client" everywhere: Server components are faster because they send less JavaScript. Only add "use client" when you need interactivity (event handlers, hooks, browser APIs).

  5. Overusing middleware for non-auth logic: Middleware runs on every matching request. Don’t put heavy computation or database calls there — it blocks the response.

Practice Questions

  1. What is the difference between getStaticProps and getServerSideProps? getStaticProps runs at build time (once), while getServerSideProps runs on every request. Use SSG for content that doesn’t change often, SSR for real-time data.

  2. What does fallback: "blocking" do in getStaticPaths? It means paths not returned by getStaticPaths are generated on first visit. The user waits for the page to build once, then it’s cached for subsequent visitors.

  3. How do you create a client component in the App Router? Add "use client" at the top of the file. This tells Next.js to send the JavaScript bundle to the browser for interactivity.

  4. What is ISR and when would you use it? Incremental Static Regeneration (ISR) updates static pages after deployment by re-fetching data at a set interval. Use it for content that updates periodically, like a blog with hourly news.

  5. Why use next/image instead of a regular <img> tag? next/image automatically optimizes images (resize, WebP conversion, lazy loading, responsive sizes), reducing page weight and improving Core Web Vitals.

Challenge

Build a blog with ISR: Create a Next.js app with app/ directory. Set up a dynamic route app/blog/[slug]/page.js that uses generateStaticParams (the App Router equivalent of getStaticPaths) and fetches data from a mock API. Set revalidate to 60 seconds for ISR. Add a loading.js file for a loading state.

FAQ

What is the difference between Pages Router and App Router?
The Pages Router uses pages/ with getStaticProps/getServerSideProps. The App Router uses app/ with server components by default, a simpler data fetching model, and support for layouts, loading states, and error boundaries.
Can I use both routers in the same project?
Yes. Next.js supports incremental adoption — you can have both pages/ and app/ folders. This is useful for migrating gradually.
Is Next.js free?
Next.js is open-source and free. Vercel offers paid hosting with additional features, but you can deploy Next.js anywhere — AWS, Netlify, your own server.
Does Next.js replace React?
No. Next.js builds on React. Everything you know about React components, hooks, and state management applies inside Next.js.

Try It Yourself

Create a new Next.js project and build a simple blog:

npx create-next-app@latest my-blog
cd my-blog
// app/page.js
async function HomePage() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts");
  const posts = await res.json();

  return (
    <div>
      <h1>My ISR Blog</h1>
      {posts.slice(0, 5).map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.body}</p>
        </article>
      ))}
    </div>
  );
}

export default HomePage;

Expected output: A page displaying 5 blog post titles with body text, fetched from JSONPlaceholder and rendered on the server.

What’s Next

TopicDescription
React Fundamentals
Master the library Next.js is built on
React Advanced Patterns
Hooks, context, and performance optimization
Express.js Backend
Compare Next.js API routes with Express

Related terms: React, JavaScript, Node.js, REST API, CSS

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro