Skip to main content

What is NextJS?

NextJS is a React framework for building full-stack web applications. It provides additional structure, features, and optimizations for your React applications, including:
  • File-based routing - No need to configure routes manually
  • Server-side rendering (SSR) - Pre-render pages on the server
  • Static site generation (SSG) - Generate static HTML at build time
  • API routes - Build your backend API within the same project
  • Automatic code splitting - Better performance out of the box
This course covers both the traditional Pages Router (section 25) and the modern App Router (section 25+), giving you a complete understanding of NextJS development.

Project Setup

Create a new NextJS project:
npx create-next-app@latest

Package Configuration

Here’s a typical NextJS project setup:
package.json
{
  "name": "nextjs-course",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^13.4.19",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}

dev

Runs development server with hot reloading

build

Creates optimized production build

start

Runs production server

export

Exports static HTML files

Pages Router Fundamentals

The traditional NextJS routing system uses a pages/ directory where each file automatically becomes a route.

Creating Your First Page

pages/news.js
// our-domain.com/news

function NewsPage() {
  return <h1>The News Page</h1>
}

export default NewsPage;
File names in the pages/ directory directly correspond to URL paths. pages/news.js/news

Dynamic Routes

Create dynamic routes using square brackets [param] in file names:
pages/news/[newsId].js
// our-domain.com/news/something-important

function DetailPage() {
  return <h1>The Detail Page</h1>
}

export default DetailPage;

Data Fetching Methods

NextJS provides several methods for fetching data at different stages of the rendering process.

Static Site Generation (SSG)

Use getStaticProps to fetch data at build time:
pages/index.js
import MeetupList from '../components/meetups/MeetupList';

const DUMMY_MEETUPS = [
  {
    id: 'm1',
    title: 'A First Meetup',
    image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Stadtbild_M%C3%BCnchen.jpg/1280px-Stadtbild_M%C3%BCnchen.jpg',
    address: 'Some address 5, 12345 Some City',
    description: 'This is a first meetup!',
  },
  {
    id: 'm2',
    title: 'A Second Meetup',
    image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Stadtbild_M%C3%BCnchen.jpg/1280px-Stadtbild_M%C3%BCnchen.jpg',
    address: 'Some address 10, 12345 Some City',
    description: 'This is a second meetup!',
  },
];

function HomePage(props) {
  return <MeetupList meetups={props.meetups} />;
}

export async function getStaticProps() {
  // fetch data from an API
  return {
    props: {
      meetups: DUMMY_MEETUPS
    }
  }; 
}

export default HomePage;
  • Data doesn’t change frequently
  • Content can be pre-rendered at build time
  • SEO is important
  • Page must be fast (pre-rendered HTML)

Incremental Static Regeneration (ISR)

Add revalidate to regenerate pages in the background:
pages/index.js
export async function getStaticProps() {
  // fetch data from an API
  return {
    props: {
      meetups: DUMMY_MEETUPS
    },
    revalidate: 1 // Regenerate page every 1 second if there's a request
  }; 
}
revalidate is in seconds. Setting it too low can cause unnecessary regenerations.

Server-Side Rendering (SSR)

Use getServerSideProps to fetch data on every request:
pages/index.js
export async function getServerSideProps(context) {
  const req = context.req;
  const res = context.res;

  // fetch data from an API

  return {
    props: {
      meetups: DUMMY_MEETUPS
    }
  };
}

SSR vs SSG

SSR: Data fetched on every request - always fresh but slowerSSG: Data fetched at build time - faster but may be stale

The _app.js File

The _app.js file is a wrapper around all your pages:
pages/_app.js
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp;
Use _app.js to:
  • Add global layouts
  • Include global CSS
  • Persist state between page changes
  • Add global error handling

API Routes

Create API endpoints inside the pages/api/ directory:
pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello from NextJS!' })
}
Access this endpoint at /api/hello.

Key Concepts Summary

1

File-based Routing

Every file in pages/ becomes a route automatically
2

Pre-rendering

Pages are pre-rendered by default for better performance and SEO
3

Data Fetching

Use getStaticProps, getServerSideProps, or getStaticPaths for data
4

API Routes

Build backend endpoints in the same project using pages/api/

Next Steps

App Router

Learn the modern App Router with enhanced features

Server Components

Understand React Server Components in NextJS

Build docs developers (and LLMs) love