Skip to content
FullStackDostFullStackDostLearn · Build · Level Up
  • All Courses
  • Updates
  • My Account
  • Practice
  • Data Strcture
  • FSD
  • All Courses
  • Updates
  • My Account
  • Practice
  • Data Strcture
  • FSD
  • Home
  • Web development

Next.Js (React.JS framework) 12 Sections142 Lessons1 Quiz10 Weeks

Curriculum

  • 12 Sections
  • 142 Lessons
  • 10 Weeks
Expand all sectionsCollapse all sections
  • Introduction to Next.js
    9 Items
    Introduction to Next JS and comparison with other frameworks.
    • 1.1
      What is Next.js?
      10 Minutes
    • 1.2
      Why use Next.js?
    • 1.3
      Next.js vs React
      10 Minutes
    • 1.4
      Next.js vs other frameworks
    • 1.5
      Key features and achitecture
    • 1.6
      How Rendering Works in Next.js
    • 1.7
      App Router vs. Pages Router: Navigating Next.js Routing Systems
    • 1.8
      Prerequisites: HTML, CSS, JavaScript and React
    • 1.9
      Introduction to Next JS
      10 Minutes5 Questions
  • Installation and setup
    9 Items
    Installation and setup Next.js
    • 2.1
      Node.js and environment setup
    • 2.2
      Create a Next.js application
      15 Minutes
    • 2.3
      Run the development server
    • 2.4
      Project folder structure
    • 2.5
      Understanding package.json and scripts
    • 2.6
      TypeScript setup
    • 2.7
      ESLint and code quality
    • 2.8
      Path aliases and the src directory
    • 2.9
      Development vs production builds
  • Routing, pages and layout
    15 Items
    Routing, pages and layout
    • 3.1
      File-system-based routing
    • 3.2
      Creating pages with page.tsx
    • 3.3
      Shared layouts with layout.tsx
    • 3.4
      Nested layouts
    • 3.5
      Link component and navigation
    • 3.6
      Dynamic route segments
    • 3.7
      Catch-all and optional catch-all routes
    • 3.8
      Route groups
    • 3.9
      Private folders
    • 3.10
      Loading UI with loading.tsx
    • 3.11
      Error handling with error.tsx
    • 3.12
      not-found.tsx
    • 3.13
      Parallel routes
    • 3.14
      Intercepting routes
    • 3.15
      Programmatic navigation and redirects
  • React component and fundamentals
    11 Items
    React component and fundamentals
    • 4.1
      React components in Next.js
    • 4.2
      Server Components
    • 4.3
      Client Components
    • 4.4
      The use client directive
    • 4.5
      Choosing server or client rendering
    • 4.6
      Composing server and client components
    • 4.7
      Props and component reuse
    • 4.8
      State and event handlers
    • 4.9
      Forms and controlled inputs
    • 4.10
      Context and providers
    • 4.11
      Third-party client libraries
  • Styling, assets and user interface (UI)
    10 Items
    • 5.1
      Global CSS
    • 5.2
      CSS Modules
    • 5.3
      Tailwind CSS
    • 5.4
      Sass and CSS-in-JS
    • 5.5
      Fonts with next/font
    • 5.6
      mages with next/image
    • 5.7
      Static assets and the public folder
    • 5.8
      Responsive design
    • 5.9
      Layouts and reusable UI patterns
    • 5.10
      Scripts with next/script
  • Data fetching and rendering
    13 Items
    • 6.1
      Fetching data in Server Components
    • 6.2
      Using the fetch API
    • 6.3
      Database and ORM integration
    • 6.4
      Fetching in Client Components
    • 6.5
      Sequential vs parallel fetching
    • 6.6
      Data loading states
    • 6.7
      Streaming and Suspense
    • 6.8
      Static rendering
    • 6.9
      Dynamic rendering
    • 6.10
      Server-side rendering concepts
    • 6.11
      Client-side rendering
    • 6.12
      Partial prerendering concepts
    • 6.13
      Environment variables and server-only code
  • Caching and data updates
    11 Items
    • 7.1
      Understanding cache fundamentals
    • 7.2
      Data Cache and rendered output
    • 7.3
      Cache Components and the use cache directive
    • 7.4
      Cache boundaries and lifetimes
    • 7.5
      Revalidation strategies
    • 7.6
      Time-based revalidation
    • 7.7
      On-demand revalidation
    • 7.8
      revalidatePath
    • 7.9
      revalidateTag
    • 7.10
      Request deduplication
    • 7.11
      Optimistic UI and fresh data
  • Backend development and mutations
    12 Items
    • 8.1
      Route Handlers
    • 8.2
      GET, POST, PUT, PATCH and DELETE
    • 8.3
      NextRequest and NextResponse
    • 8.4
      Server Functions and Server Actions
    • 8.5
      Form submissions
    • 8.6
      Validation and error handling
    • 8.7
      Database CRUD operations
    • 8.8
      Cookies and headers
    • 8.9
      File uploads
    • 8.10
      Webhooks
    • 8.11
      Backend-for-Frontend patterns
    • 8.12
      API security
  • Authentication and Security
    12 Items
    • 9.1
      Authentication vs authorization
    • 9.2
      Sessions and cookies
    • 9.3
      Login and logout flows
    • 9.4
      Protecting routes and layouts
    • 9.5
      Authorization checks near data access
    • 9.6
      Role-based access control
    • 9.7
      Using authentication libraries
    • 9.8
      Environment secrets
    • 9.9
      Input validation
    • 9.10
      CSRF and request security
    • 9.11
      Content Security Policy
    • 9.12
      Data security and safe serialization
  • SEO, performance and accessibility
    14 Items
    • 10.1
      Metadata API
    • 10.2
      Dynamic metadata
    • 10.3
      Open Graph images
    • 10.4
      Sitemaps and robots.txt
    • 10.5
      Canonical URLs
    • 10.6
      Font and image optimization
    • 10.7
      Link prefetching
    • 10.8
      Lazy loading
    • 10.9
      Bundle analysis
    • 10.10
      Core Web Vitals
    • 10.11
      Accessibility fundamentals
    • 10.12
      Analytics and Speed Insights
    • 10.13
      Internationalization
    • 10.14
      Redirects and rewrites
  • Testing, deployment and production
    13 Items
    • 11.1
      Unit and component testing
    • 11.2
      Jest and Vitest
    • 11.3
      End-to-end testing with Playwright or Cypress
    • 11.4
      Build and production start
    • 11.5
      Deployment to a managed platform
    • 11.6
      Self-hosting with Node.js or Docker
    • 11.7
      Static export
    • 11.8
      CI/CD pipelines
    • 11.9
      Logging and monitoring
    • 11.10
      Instrumentation and OpenTelemetry
    • 11.11
      Production security checklist
    • 11.12
      Troubleshooting and debugging
    • 11.13
      Upgrading Next.js and codemods
  • Advanced topics and Pages Router
    14 Items
    • 12.1
      Middleware concepts and Proxy conventions
    • 12.2
      Edge Runtime
    • 12.3
      Custom servers
    • 12.4
      Multi-Zones
    • 12.5
      Progressive migration from Pages Router
    • 12.6
      Pages Router pages and layouts
    • 12.7
      getStaticProps
    • 12.8
      getServerSideProps
    • 12.9
      getStaticPaths
    • 12.10
      API Routes
    • 12.11
      Pages Router data fetching
    • 12.12
      useRouter and router events
    • 12.13
      Legacy image and head APIs
    • 12.14
      Migrating Pages Router applications

App Router vs. Pages Router: Navigating Next.js Routing Systems

Introduction: Navigating Next.js Routing

Namaste, future full-stack developers! Welcome to this crucial lesson where we’ll demystify one of Next.js’s most important concepts: its routing systems. Next.js, being a powerful React framework, has evolved, and with that evolution came a significant update to how we handle routing. You’ll encounter two primary systems: the App Router and the Pages Router. Understanding both is key to building modern Next.js applications and maintaining existing ones.

Why two routers, you ask? Think of it like this: as web development advances, so do the tools we use. The App Router represents a leap forward, bringing powerful new features like Server Components and nested layouts. However, the Pages Router remains incredibly relevant, especially for legacy projects or when you need to understand existing codebases. In this lesson, we’ll break down both, compare their features, and guide you on when to use each.

Why Two Routers? A Brief History

The Pages Router was Next.js’s original routing system. It’s based on the pages/ directory and uses a file-system-based routing approach, where each file in pages/ directly maps to a route. It’s intuitive and served the community well for years, introducing concepts like server-side rendering (SSR) and static site generation (SSG) with functions like getStaticProps and getServerSideProps.

The App Router, introduced in Next.js 13, is built on React Server Components and uses the app/ directory. It’s designed to be more flexible, performant, and to leverage the full potential of React’s latest features. It offers new paradigms for data fetching, caching, and nested layouts, aiming to simplify complex application structures and improve user experience.

The Pages Router: A Familiar Path

The Pages Router is straightforward: a file in the pages/ directory becomes a route. This system is still widely used and powers countless Next.js applications.

Structure and Core Concepts

In the Pages Router, your routes are defined by files within the pages/ directory. For example:

  • pages/index.tsx maps to /
  • pages/about.tsx maps to /about
  • pages/products/index.tsx maps to /products
  • pages/products/[id].tsx maps to /products/:id (a dynamic route)

API routes are also defined within this system, inside pages/api/.

Example: Basic Page and Dynamic Route

Let’s look at a simple product listing and a dynamic product detail page using the Pages Router.

// pages/products/index.tsx
import React from 'react';
import Link from 'next/link';
interface Product {
  id: string;
  name: string;
}
interface ProductsProps {
  products: Product[];
}
export async function getStaticProps() {
  // In a real app, you'd fetch this from an API
  const products: Product[] = [
    { id: '1', name: 'Laptop' },
    { id: '2', name: 'Smartphone' },
    { id: '3', name: 'Headphones' },
  ];
  return {
    props: { products },
  };
}
const ProductsPage: React.FC<ProductsProps> = ({ products }) => {
  return (
    <div>
      <h1>Our Products</h1>
      <ul>
        {products.map((product) => (
          <li key={product.id}>
            <Link href={`/products/${product.id}`}>{product.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
};
export default ProductsPage;
// pages/products/[id].tsx
import React from 'react';
import { useRouter } from 'next/router';
interface Product {
  id: string;
  name: string;
  description: string;
}
interface ProductDetailProps {
  product: Product;
}
export async function getStaticPaths() {
  const products: Product[] = [
    { id: '1', name: 'Laptop', description: 'Powerful computing' },
    { id: '2', name: 'Smartphone', description: 'Smart communication' },
    { id: '3', name: 'Headphones', description: 'Immersive audio' },
  ];
  const paths = products.map((product) => ({
    params: { id: product.id },
  }));
  return { paths, fallback: false };
}
export async function getStaticProps({ params }: { params: { id: string } }) {
  const products: Product[] = [
    { id: '1', name: 'Laptop', description: 'Powerful computing' },
    { id: '2', name: 'Smartphone', description: 'Smart communication' },
    { id: '3', name: 'Headphones', description: 'Immersive audio' },
  ];
  const product = products.find((p) => p.id === params.id);
  return { props: { product } };
}
const ProductDetailPage: React.FC<ProductDetailProps> = ({ product }) => {
  const router = useRouter();
  if (router.isFallback) {
    return <div>Loading...</div>;
  }
  if (!product) {
    return <div>Product not found.</div>;
  }
  return (
    <div>
      <h1>{product.name}</h1>
      <p>ID: {product.id}</p>
      <p>Description: {product.description}</p>
      <button onClick={() => router.back()}>Go Back</button>
    </div>
  );
};
export default ProductDetailPage;

The App Router: The Modern Approach

The App Router is the future of Next.js. It introduces new paradigms, most notably React Server Components, providing a powerful way to build highly performant and flexible applications.

Structure and Core Concepts

The App Router operates within the app/ directory. Unlike the Pages Router where each file is a route, in the App Router, folders define routes, and special files within those folders define the UI and behavior.

  • app/page.tsx maps to / (the root route)
  • app/dashboard/page.tsx maps to /dashboard
  • app/products/[id]/page.tsx maps to /products/:id

The key idea is that routes are defined by nested folders, and a page.tsx file within a folder is required to make that folder publicly accessible as a route segment.

Server Components and Layouts

A fundamental shift with the App Router is the default use of React Server Components. By default, components in the app/ directory are Server Components, which render on the server, reducing client-side JavaScript and improving initial page load performance.

Layouts are another powerful concept. You can define shared UI for a segment and its children using layout.tsx. Layouts are Server Components by default and persist across navigations, maintaining state and avoiding re-renders.

Example: Nested Layout and Dynamic Route

Let’s recreate our product listing with a nested layout using the App Router.

// app/products/layout.tsx
import React from 'react';
import Link from 'next/link';
export default function ProductsLayout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <nav style={{ borderBottom: '1px solid #ccc', padding: '10px 0' }}>
        <Link href="/">Home</Link> | <Link href="/products">All Products</Link>
      </nav>
      <main>
        {children}
      </main>
    </div>
  );
}
// app/products/page.tsx
import Link from 'next/link';
interface Product {
  id: string;
  name: string;
}
// This component is a Server Component by default
export default async function ProductsPage() {
  // Data fetching directly in Server Components
  const products: Product[] = [
    { id: '1', name: 'Laptop' },
    { id: '2', name: 'Smartphone' },
    { id: '3', name: 'Headphones' },
  ];
  return (
    <div>
      <h1>Our Products (App Router)</h1>
      <ul>
        {products.map((product) => (
          <li key={product.id}>
            <Link href={`/products/${product.id}`}>{product.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}
// app/products/[id]/page.tsx
import { notFound } from 'next/navigation';
interface Product {
  id: string;
  name: string;
  description: string;
}
interface ProductDetailPageProps {
  params: { id: string };
}
export default async function ProductDetailPage({ params }: ProductDetailPageProps) {
  const products: Product[] = [
    { id: '1', name: 'Laptop', description: 'Powerful computing' },
    { id: '2', name: 'Smartphone', description: 'Smart communication' },
    { id: '3', name: 'Headphones', description: 'Immersive audio' },
  ];
  const product = products.find((p) => p.id === params.id);
  if (!product) {
    notFound(); // Use notFound() for 404s in App Router
  }
  return (
    <div>
      <h1>{product.name}</h1>
      <p>ID: {product.id}</p>
      <p>Description: {product.description}</p>
      {/* Navigation can be handled with Link or useRouter from 'next/navigation' */}
    </div>
  );
}

Special Files: Powering Your App

The App Router utilizes several special files to define UI and behavior within a route segment:

  • page.tsx: Renders the unique UI for a route segment.
  • layout.tsx: Defines shared UI for a segment and its children.
  • loading.tsx: Displays a loading UI while a segment’s content is loading.
  • error.tsx: Catches errors within a route segment and displays a fallback UI.
  • not-found.tsx: Renders a 404 UI when a route is not found within a segment.
  • route.ts (or .js, .mjs, .cjs): Defines Route Handlers, which are custom backend API endpoints, replacing pages/api.
  • template.tsx: Similar to layout.tsx but creates a new instance for each child, allowing state to reset.

App Router vs. Pages Router: A Side-by-Side Comparison

Let’s summarize the key differences to help solidify your understanding:

FeatureApp Router (app/)Pages Router (pages/)
Directoryapp/pages/
Routing LogicFolder-based routing, page.tsx defines route UI.File-based routing, each file in pages/ is a route.
Default Component ModelReact Server Components (RSC) by default. Use 'use client'; for Client Components.Traditional React Client Components.
Shared Layoutslayout.tsx for nested, persistent layouts.Custom layouts often implemented with _app.tsx or higher-order components.
Data Fetchingfetch() API (extended with caching and revalidation), async/await directly in Server Components, streaming.getStaticProps, getServerSideProps, getStaticPaths for server-side data fetching. Client-side fetching with useEffect or SWR.
Loading UIloading.tsx file for instant loading states with Suspense.Typically managed with component state or external libraries.
Error Handlingerror.tsx file for route-segment error boundaries.Custom _error.tsx page for application-level errors, or component-level error boundaries.
Not Found UInot-found.tsx file for 404 pages within a segment. Use notFound() function.Custom 404.tsx page.
API Endpointsroute.ts (Route Handlers) within app/ folders.Files within pages/api/.
Client-Side Navigationnext/link and useRouter from next/navigation.next/link and useRouter from next/router.

When to Choose Which Router

Making the right choice depends on your project’s needs and current stage.

Starting New Projects

Always prioritize the App Router for new Next.js projects. It’s the recommended and actively developed routing system, offering superior performance, a simpler data fetching model, and better scalability with React Server Components.

Maintaining Existing Applications

If you’re working on an existing Next.js application that uses the pages/ directory, you’ll need to understand and continue using the Pages Router. Migrating a large application can be a significant undertaking, and often, maintaining the existing system is the most practical approach.

Migrating Projects

Next.js supports coexistence of both routers during a migration. This means you can incrementally move parts of your application from pages/ to app/. This is a powerful feature, but it requires careful planning to avoid route conflicts and ensure correct API usage.

Using Both in Harmony (Carefully!)

When using both routers in the same application, remember these critical points:

  • Avoid Route Conflicts: A route cannot be defined in both app/ and pages/. If you have app/dashboard/page.tsx, you cannot have pages/dashboard.tsx.
  • Separate APIs: The useRouter hook from next/router is for the Pages Router, while the one from next/navigation is for the App Router. Do not mix them indiscriminately within the same component or context.
  • Data Fetching: Understand that data fetching patterns differ significantly. getStaticProps/getServerSideProps are exclusive to the Pages Router. In the App Router, you’ll use fetch() or other data fetching libraries directly within Server Components.

Practice Exercise: Route Explorer Challenge

Let’s get hands-on! Your task is to create a small Next.js project and implement a simple user profile page using both routing systems.

  1. Setup: Create a new Next.js project (you can choose to initialize with the App Router, then add a pages/ directory manually).
  2. Pages Router Profile:
    • Create a file at pages/users/[username].tsx.
    • Inside this file, use getServerSideProps to fetch user data based on the username parameter. For simplicity, you can mock data (e.g., if username === 'dost', return a user object).
    • Display the user’s name and a short bio.
  3. App Router Profile:
    • Create a folder structure at app/profile/[username]/page.tsx.
    • Inside this file, fetch the same user data directly within the Server Component (using async/await) based on the username parameter from params.
    • Display the user’s name and bio, similar to the Pages Router version.
  4. Observation: Navigate to /users/dost and /profile/dost. Observe how the URLs map, and reflect on the differences in data fetching and component structure.

This exercise will give you practical experience with both systems and highlight their distinct approaches.

Summary: Mastering Next.js Routing

You’ve now got a solid understanding of Next.js’s two powerful routing systems. The Pages Router, with its file-based approach, is a robust system for existing applications. The App Router, leveraging React Server Components and a folder-based structure, is the modern, recommended choice for new projects, offering enhanced performance and flexibility.

Remember, the key is to understand their fundamental differences, especially concerning data fetching, layouts, and the correct usage of routing hooks. By mastering both, you’ll be well-equipped to tackle any Next.js project, whether it’s a brand-new build or maintaining an established application. Keep practicing, and you’ll navigate Next.js routing like a pro! All the best!

Leave a Reply Cancel reply

You must be logged in to post a comment.

How Rendering Works in Next.js
Prev
Prerequisites: HTML, CSS, JavaScript and React
Next

Copyright © 2026 FullStackDost. All Rights Reserved.

  • Privacy Policy
  • Terms of Service
  • Contact Support

Powered by EduPress