Home/Blog/Web Development/Next.js tutorial with examples: Build better React apps with Next
Home/Blog/Web Development/Next.js tutorial with examples: Build better React apps with Next

Next.js tutorial with examples: Build better React apps with Next

12 min read
Mar 05, 2025
content
What is Next.js?
Key features of Next.js
Why use Next.js?
Pros:
Cons:
When to use Next.js
Getting started with Next.js
Step 1: Requirements and environment
Step 2: Initialize a new Next.js project
Step 3: Run the application
Step 4: Understand the Next.js folder structure
Step 5: Add routing and navigation to the Next.js app
1. Defining routes
2. Nested routes
3. Dynamic routes
4. Linking between pages
Step 6: Understand Next.js data fetching with App Router
1. SSR data fetching
2. SSG data fetching
3. ISR data fetching
Continue learning Next.js

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

Key takeaways:

  • Next.js builds on React by adding features like server-side rendering (SSR) and static site generation (SSG), optimizing performance and SEO.

  • SSR and SSG improve page load times and search engine rankings, making Next.js ideal for content-heavy websites.

  • The Next.js App Router allows developers to create complex and dynamic routes using dynamic segments like user IDs and product slugs, enhancing your application’s flexibility.

  • Incremental static regeneration (ISR) in Next.js allows developers to update static pages after they have been built. This means static pages can be regenerated on demand when a certain condition is met.

  • Automatic code splitting and image optimization ensure that applications load faster by serving only necessary code and optimizing media assets without extra configuration.

Building high-performance, scalable, and SEO-friendly web applications can be challenging, especially when working with React. While React excels at creating dynamic user interfaces, achieving optimal performance and SEO often requires additional effort. This is where Next.js comes in. As a React framework, Next.js empowers developers to easily create fast, SEO-friendly applications without complexity.

With features like server-side rendering (SSR), static site generation (SSG), and the new App Router introduced in Next.js 13, it has become the go-to choice for building modern web applications. Full stack developers love Next.js for its ability to deliver optimized, reactive websites by combining client-side React with powerful server-side capabilities.

In this blog, we’ll help you start with Next.js by covering the main concepts you need to know before building optimized sites.

Next.js - The ultimate way to build React apps

Cover
Next.js - The ultimate way to build React apps

React is an amazing framework that allows you to build front-ends that are unmatched in speed, functionality, and ease of use. Where React falls short though is its ability to optimize for search engines. That’s where Next.js comes in. In this course, you will learn to build a giphy search app using the giphy.com API. To kick things off, you’ll learn how to statically optimize a Next.js page, creating an ultra fast loading experience for users. You’ll then dive into the inner workings of creating your giphy search app. In the back half of the course, you will learn how to optimize for SEO, and how to deploy your application. By the end, you will have a great new framework to add to your resume and a new shiny application to add to your portfolio.

5hrs
Intermediate
12 Playgrounds
6 Quizzes

What is Next.js?#

Next.js is an open-source React front-end framework that adds optimization capabilities like server-side rendering (SSR) and static-site generation. It builds on the React library, meaning Next.js applications take the benefits of React and add additional features.

Key features of Next.js#

Let’s look at some of the key features offered by Next.js:

  • Server-side rendering (SSR): SSR allows the server to access all required data and process the JavaScript together to render the page. Then, the page is sent back to the browser and immediately rendered. SSR reduces page load times and enhances responsiveness, improving user experience.

  • Static site generation (SSG): SSG prerenders pages at build time, generating static HTML files that can be served instantly. This approach offers fast load times and scalability, ideal for content that doesn’t change frequently.

  • Search engine optimization (SEO): SSR and SSG improve SEO by providing fully rendered HTML to search engines, which enhances crawlability and indexing. This helps the site to show up higher on search engine results pages, making websites rank better for SEO because they load faster, and SEO trackers can scan more of the site content.

  • <head> tag: Next.js also allows you to edit a site’s <head> tag, which you cannot do in React. The <head> tag is a core part of a web page’s metadata and contributes to the site’s SEO ranking.

  • New App Router: Introduced in Next.js 13, Next.js uses React Server Components and offers a more intuitive file-based routing system.

Overall, Next.js is considered a more fully-featured version of React that maintains the intuitiveness the React framework is known for.

Want to build a professional project in Next.js? Try out this project: Build an Interactive E-Library Using Next.js and Tailwind.

Why use Next.js?#

The main advantage of Next.js is that it leverages SSR and SSG to deliver content faster, resulting in improved performance, a better user experience, and boosted SEO rankings. With features like automatic code splitting and built-in routing, Next.js reduces the boilerplate code you need to write, letting you focus on building features rather than setting up configurations.

Additionally, the introduction of the App Router in Next.js 13 brings React Server Components into the mix, allowing for better performance and a more seamless development experience.

Pros:#

  • Next.js apps load considerably faster than React apps due to out-of-the-box server-side rendering.

  • Supports exporting static sites for better performance and scalability.

  • Quick to learn for anyone with previous React experience.

  • Automatic code splitting for pages enhances performance by loading only the necessary code for each page.

  • Easily to build internal APIs through built-in API routes and create API endpoints.

  • The new App Router simplifies routing and enhances performance with React Server Components.

  • Quick to add plugins to customize Next.js to your specific page’s needs.

  • Maintains the benefits of React, such as intuitive component-driven creation, front-end state system, and high popularity.

Cons:#

  • The new App Router and React Server Components may require time to learn.

  • Another downside of Next.js is that it’s an opinionated framework. This means it wants you to use a specific method and toolset to construct your apps, which might limit flexibility for some projects.

However, the preferences of Next.js will fit well within the scope of most projects.

Fun fact: Educative recently switched to Next.js on top of React. If you’ve used Educative in the last few months, you’ve already enjoyed some benefits of Next.js!

When to use Next.js#

Next.js is a powerful framework that shines in specific scenarios due to its versatile and feature-rich nature. Here are the key use cases:

  • When creating SEO-friendly landing pages or home pages:
    Next.js is best suited for creating optimized landing pages and homepages that rely on organic search traffic. Its advanced SEO capabilities, like Server-Side Rendering (SSR) and Static Site Generation (SSG), make it ideal for such use cases.

  • When building dynamic web applications:
    Next.js is versatile enough to support dynamic web applications and e-commerce platforms, offering robust performance through SSR. This ensures a consistent and smooth user experience across various devices.

  • When creating secure applications with authentication:
    Next.js is an excellent choice for building secure web applications that require robust authentication. With SSR, API routes, and easy integration with authentication libraries, developers can implement secure mechanisms effectively.

Get hands-on experience with Next.js app development with our Product Review and Feedback System Using the Next.js project.

Getting started with Next.js#

Let’s examine an example of a basic Next.js application to understand its structure and functionality. We’ll then examine each step of setting up a Next.js application individually.

Step 1: Requirements and environment#

Before we get started, let’s set up everything you need. Before you download Next.js, you’ll need npm and npx along with Node.js.

You can install Node.js on its official site. Enter node—v into your command prompt to confirm it’s downloaded correctly. Usually, npm and npx come with your Node.js installation.

Note: To confirm that npm and npx have been installed, enter npm -v and npx -v into your command prompt. Each will return its version, respectively.

Step 2: Initialize a new Next.js project#

You can create a fresh Next.js application using the create-next-app command. Using create-next-app is straightforward as all you need to do is enter npm create-next-app <app-name> into your command prompt, where <app-name> refers to the name of your application.

npx create-next-app@latest my-nextjs-app
Initialize a new Next.js project

Step 3: Run the application#

To run the default application, you need to navigate to your project directory and start the development server as follows:

cd my-nextjs-app
npm run dev
Run the application

You’ll see the default Next.js page on http://localhost:3000.

Step 4: Understand the Next.js folder structure#

Understanding the Next.js folder structure is essential for efficient project management and scalability. A fresh Next.js project typically contains the following folders:

my-nextjs-app/
├── app/
│ ├── layout.js
│ ├── page.js
│ └── globals.css
├── public/
│ ├── vercel.svg
├── next.config.js
├── package.json
└── .gitignore
The Next.js folder structure

Folder breakdown:

  • The app directory contains all application-specific files, including pages, layouts, and API routes.

    • layout.js: Defines the layout for your application, wrapping around all pages.

    • page.js: Represents the main page (replaces index.js in the pages directory).

  • The public directory serves static assets like images, icons, and other files that don’t require processing.

The app/page.js file serves as the home page of the application:

import Image from "next/image";
import styles from "./page.module.css";
export default function Home() {
return (
<div className={styles.page}>
<main className={styles.main}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol>
<li>
Get started by editing <code>app/page.js</code>.
</li>
<li>Save and see your changes instantly.</li>
</ol>
<div className={styles.ctas}>
<a
className={styles.primary}
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className={styles.logo}
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
className={styles.secondary}
>
Read our docs
</a>
</div>
</main>
<footer className={styles.footer}>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org →
</a>
</footer>
</div>
);
}
Sample app/page.js file

Step 5: Add routing and navigation to the Next.js app #

Navigation refers to the ways your users can navigate through your Next.js website. The App Router simplifies routing with its flexible file-based system, automatically creating routes based on the file structure within the app directory in Next.js 13. There are various aspects of routing and navigation in Next.js using the App Router, which we will look at below.

Learn more about Next.js routing with the App Router with this blog: Understanding routing in Next.js with the App Router.

1. Defining routes#

Static routes are the simplest routing in Next.js, where each page.js file corresponds to a specific URL path. Each folder represents a route segment, and the page.js file within a folder represents a page for that route.

app/
├── page.js # Renders at / route
├── about/
│ └── page.js # Renders at /about route
└── contact/
│ └── page.js # Renders at /contact route
├── dashboard/
│ └── page.js # Renders at /dashboard route
Defining routes

2. Nested routes#

Nested routes allow you to create more complex URL structures by organizing files within nested folders. This is particularly useful for sections of your site that have their sub-pages. For example, in a user dashboard, /dashboard could serve as the main page, while /dashboard/settings act as a sub-page for managing settings. Nested routes help you keep related pages well-organized, making your project structure tidy and intuitive.

app/
├── dashboard/
│ ├── settings/
│ │ └── page.js # Renders at /dashboard/settings route
│ └── page.js # Renders at /dashboard route
Nested routes

3. Dynamic routes#

Dynamic routes handle variable URL segments, allowing your application to respond to different parameters. This is essential for creating pages that display content based on dynamic data, such as user profiles, blog posts, or product details.

Check out this project: Next.js Internationalization: Building a Multilingual Blog App to see dynamic routing in action.

Dynamic routes are defined by placing folder names in square brackets, e.g., [id] or [postId]. This allows Next.js to treat part of the URL as a variable. Consider the example below:

app/
├── user/
│ └── [id]/
│ └── page.js # Renders at /user/:id
Dynamic routes

With this setup, users can enter their ID in the URL and immediately go to their user details page rather than starting at users. In other words, you can enter your user ID, /users/9, to reach a dynamic page that populates with the user details relative to the ID entered.

To get hands-on experience with Next.js routing, refer to the Build a Music Sharing App with Next.js and the MERN Stack project.

4. Linking between pages#

You can also introduce client-side click-through links to allow users to navigate the site without the URL bar. The built-in Link component is the key to linking in Next.js. It takes an href attribute populated with the file route of the destination component. This will link the current page and the page found at the entered route.

import Link from 'next/link';
export default function HomePage() {
return <Link href="/settings">Go to Settings</Link>;
}
Linking between pages

Step 6: Understand Next.js data fetching with App Router#

Next.js’s App Router moves away from the traditional getServerSidePropsThis method fetched data on every request, making it suitable for dynamic content, such as personalized dashboards or frequently updated reports. The data was fetched on the server before sending the HTML to the client., getStaticPropsThis function lets us fetch data at build time, making it ideal for pages that rarely change, such as a blog home page or a product catalog. The static HTML includes the fetched data, ensuring fast loading and better SEO., and getStaticPathsThis is used alongside getStaticProps for dynamic routes, enabling us to prerender pages for specific paths at build time. For example, a blog app would generate static pages for each post based on its slug. used in the pages directory. Instead, it leverages React Server Components, built-in Fetch API, and special functions like generateStaticParams to streamline data fetching.

This blog, Understanding Data Fetching in Next.js, explains more about data fetching strategies for the server and the client.

1. SSR data fetching#

SSR fetches data on each request, ensuring the user receives the most up-to-date content. In the App Router, SSR is integrated by fetching data directly within Server Components.

Let’s look at an example below.

export default async function ProductsPage() {
// Fetch user data from an external API
const response = await fetch('https://educative.io/api/products', {
// Ensure fresh data on every request
cache: 'no-store'
});
const products = await response.json();
return (
<ul>
{products.map((product) => (
<li key={product.id}>
<h2>{product.name}</h2>
<p>{product.description}</p>
</li>
))}
</ul>
);
}
SSR data fetching

In this example, we use the Fetch API to retrieve a list of blog posts rendered on the server. The response from fetch will be automatically cached. However, the cache: 'no-store' option ensures that data is fetched fresh on every request without caching. You can remove this option if you wish to cache the response.

2. SSG data fetching#

SSG prerenders pages at build time, producing static HTML files that users can serve quickly. This is ideal for content that doesn’t change frequently, such as blog posts or marketing pages.

Let’s look at an example below that will fetch data at build time with generateStaticParams.

// This function runs at build time to generate all possible blog post paths
export async function generateStaticParams() {
const res = await fetch('https://educative.io/blog/posts')
if (!res.ok) {
throw new Error('Failed to fetch blog posts')
}
const posts = await res.json()
// Return an array of params for each post
return posts.map((post) => ({
slug: post.slug,
}))
}
// Page component that receives params for each blog post
export default async function BlogPostPage({ params }) {
const { slug } = params
// Fetch individual blog post data
const res = await fetch(`https://educative.io/blog/posts/${slug}`, {
// Use default cache settings for SSG
cache: 'force-cache',
})
if (!res.ok) {
throw new Error('Failed to fetch blog post')
}
const post = await res.json()
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
SSG data fetching

In the example above, the generateStaticParams function generates all possible dynamic routes (e.g., /blog/my-first-post) at build time. The cache: 'force-cache' option ensures that the fetched data is cached and served as static HTML. Each blog post page is pre-rendered during the build, resulting in faster load times and better SEO.

3. ISR data fetching#

Incremental static regeneration (ISR) allows you to update static content after the site has been built without rebuilding the entire application. This is useful for content that needs periodic updates, such as news articles or product listings.

Let’s look at an example below where we will build a product listing page that updates every 60 seconds to reflect new products.

export const revalidate = 60; // Revalidate every 60 seconds
export default async function BlogPostPage() {
const response = await fetch('https://educative.io/posts')
const posts = await response.json();
return (
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>
<h1>{post.title}</h1>
<p>{post.content}</p>
</li>
))}
</ul>
</div>
)
}
ISR data fetching

The page is regenerated every 60 seconds. Users who visit within this 60-second window see the cached version. After that, the page is automatically regenerated in the background for the next visitor.

Here is a table that sums up the comparison of SSR, SSG, and ISR based on different parameters:

Feature

SSR (Server-Side Rendering)

SSG (Static Site Generation)

ISR (Incremental Static Regeneration)

Data Fetching Time

On every request

At build time

At build time, with updates at regular intervals

Performance

Slower (Server rendered on each request)

Fast (prerendered static files served)

Fast, with periodic updates

Use Case

Frequently changing data (e.g., User-specific content)

Rarely changing data (e.g., Marketing pages)

Periodically changing data (e.g., Product listings)

Caching

No caching (Fresh data every request)

Fully cached (Static HTML)

Cached with periodic regeneration

Example Cache Option

cache: 'no-store'

cache: 'force-cache'

revalidate: 60

(or desired interval)

Continue learning Next.js#

Now that you’ve had a walk-through of a Next.js application’s building blocks explore these projects for hands-on practice on Next.js:

Frequently Asked Questions

How do I start a new Next.js project?

You can run the command npx create-next-app my-app to start a new project. This will set up a basic Next.js project with all dependencies.

What is the difference between the Pages and App Router in Next.js?

How does caching work with server-side data fetching in Next.js?

How does ISR differ from SSR and SSG in Next.js?

What is the difference between Server and Client Components in Next.js?


Written By:
Hamna Waseem
Join 2.5 million developers at
Explore the catalog

Free Resources