INT257Semester 5 • 3 CreditsElective Subjects

Modern Web Application Development

This course covers modern web application development using Next.js, including project structure, routing, rendering strategies, data fetching, APIs, Server Actions, authentication, database integration, performance optimization, deployment, and industry practices.

6 Units • Notes • Model Answers • MCQs
Select Course Unit (6 Units)
Active: Unit 1
Unit 1:Unit 1: Fundamentals of Next.js and Routing
7 min read•High-Yield Unit Guide

Unit 1: Fundamentals of Next.js and Routing

Unit 1 Exam Focus & Core Takeaways

Review the core definitions, standard architectures, and syntax patterns below. Pay special attention to sections highlighted with bullet points for your mid-term and end-term subjective questions.

Unit 1: Fundamentals of Next.js and Routing

1. Introduction to Next.js Architecture

Next.js is an open-source, full-stack React framework developed by Vercel that streamlines building high-performance, search-engine-optimized, production-ready web applications. While standard React applications (such as those generated via Vite or Create React App) operate as client-rendered Single-Page Applications (SPAs), Next.js introduces a hybrid architecture combining server-side rendering, static site generation, and client-side interactivity.

Core Value Propositions of Next.js:

  • Hybrid Rendering Paradigms: Supports Static Site Generation (SSG), Server-Side Rendering (SSR), Client-Side Rendering (CSR), and Incremental Static Regeneration (ISR).
  • Zero-Configuration Bundling: Powered by Turbopack (in modern Next.js versions) and SWC (Speedy Web Compiler), offering rapid hot-reloading and minification.
  • File-System Based Routing: Eliminates external routing libraries like react-router-dom; file and folder conventions automatically dictate route URLs.
  • Built-in Optimizations: Native components for image optimization (next/image), font loading (next/font), script optimization (next/script), and metadata management.
  • Full-Stack Capabilities: Seamlessly blends frontend UI with backend Route Handlers and Server Actions without needing a standalone Node.js Express server.

Project Directory Structure: App Router vs. Pages Router

Next.js 13 introduced the App Router (app/ directory), built on React Server Components (RSC), which supersedes the legacy Pages Router (pages/ directory).

text
my-next-app/
├── app/                      # App Router root (Next.js 13+)
│   ├── favicon.ico
│   ├── globals.css           # Global stylesheets
│   ├── layout.tsx            # Mandatory Root Layout (html, body)
│   ├── page.tsx              # Home page UI (/)
│   ├── loading.tsx           # Global loading UI
│   ├── not-found.tsx         # Global 404 UI
│   ├── error.tsx             # Root error boundary ('use client')
│   ├── blog/                 # Nested route (/blog)
│   │   ├── [slug]/           # Dynamic segment (/blog/:slug)
│   │   │   └── page.tsx
│   │   └── page.tsx
│   └── api/                  # Backend Route Handlers
│       └── hello/
│           └── route.ts
├── public/                   # Static assets (images, fonts, robots.txt)
├── next.config.js            # Framework configuration
├── package.json
└── tsconfig.json

2. The App Router Conventions & Special Files

In the App Router, folders define route paths, while specific reserved filenames define user interface components and boundary behaviors for that route segment:

Special FilenameComponent RoleRendering Environment
page.jsxUnique UI for a route segment; makes the path publicly accessible.Server Component by default
layout.jsxShared layout wrapping child routes; preserves state across navigation and never re-renders.Server Component by default
template.jsxSimilar to layout.jsx, but creates a brand new component instance on every navigation (resets state & effects).Server Component by default
loading.jsxInstant fallback UI wrapped automatically inside React <Suspense>.Server Component
error.jsxError boundary wrapping child route segments in a React error boundary.Must be a Client Component ('use client')
not-found.jsxRendered when notFound() function is invoked or an unmatched URL is hit.Server Component
route.jsBackend API endpoint (HTTP methods: GET, POST, PUT, DELETE, PATCH).Server execution only

The Root Layout (app/layout.jsx)

The root layout is mandatory in every Next.js App Router application. It must define the top-level <html> and <body> tags:

jsx
// app/layout.jsx
import './globals.css';
import { Inter } from 'next/font/google';

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

export const metadata = {
  title: 'Modern Web Application',
  description: 'Built with Next.js 14 App Router'
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <header className="site-header">My Application</header>
        <main>{children}</main>
        <footer>© 2026 Modern Web Inc.</footer>
      </body>
    </html>
  );
}

3. Server Components vs. Client Components

A cornerstone of modern Next.js is React Server Components (RSC).

React Server Components (Default)

In the app/ directory, all components are Server Components by default unless explicitly instructed otherwise.

  • Execution: Execute exclusively on the web server during build or request time.
  • Bundle Weight: Emit zero JavaScript into the client browser bundle.
  • Capabilities:
    • Can directly query backend databases (PostgreSQL, Prisma, MongoDB, Redis).
    • Can securely access server environment variables and secrets without exposing them.
    • Can read the host filesystem (fs/promises).
  • Restrictions:
    • Cannot use React state or lifecycle hooks (useState, useReducer, useEffect, useLayoutEffect).
    • Cannot listen to browser DOM events (onClick, onChange, onSubmit).
    • Cannot access browser APIs (window, localStorage, navigator, document).

Client Components ('use client')

To introduce browser interactivity, developers mark a file as a Client Component using the 'use client' directive at the very top of the file:

jsx
'use client';

import React, { useState } from 'react';

export default function InteractiveCounter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked: {count} times
    </button>
  );
}
  • Pre-rendering: Client Components are still pre-rendered on the server into static HTML during initial request, then 'hydrated' by React in the browser.
  • Boundary Placement: Best practice recommends pushing 'use client' directives as far down the component tree as possible (leaf components), keeping container layouts as Server Components.

Composing Server and Client Components

Server Components can be passed into Client Components as children (slots), preserving their server-only execution benefits:

jsx
'use client';
export function ModalShell({ children }) {
  const [isOpen, setIsOpen] = useState(true);
  return isOpen ? <div className="modal">{children}</div> : null;
}

// In a Server Component page:
import { ModalShell } from './ModalShell';
import { HeavyServerData } from './HeavyServerData'; // Server Component

export default function Page() {
  return (
    <ModalShell>
      <HeavyServerData /> {/* Rendered on server, passed as JSX prop */}
    </ModalShell>
  );
}

4. Navigation and Linking

Next.js provides declarative and imperative navigation mechanisms optimized for performance:

The primary way to navigate between routes in Next.js:

jsx
import Link from 'next/link';

<Link href="/dashboard" prefetch={true} className="nav-item">
  Go to Dashboard
</Link>
  • Automatic Viewport Prefetching: Whenever a <Link> enters the browser's viewport, Next.js automatically prefetches the corresponding route bundle and server component data in the background, making page transitions nearly instantaneous.
  • Soft Navigation: Preserves React state across transitions without full page reloads.

Imperative Navigation: useRouter (next/navigation)

In Client Components, navigation can be triggered programmatically using the useRouter hook imported from next/navigation (not next/router from the legacy Pages Router):

jsx
'use client';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';

export function NavigationControls() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  const handleCheckout = () => {
    // Navigate to order page
    router.push('/checkout');
    // Replace current history entry
    // router.replace('/login');
    // Refresh current route data
    // router.refresh();
  };

  return <button onClick={handleCheckout}>Checkout ({pathname})</button>;
}

Server-Side Redirection

In Server Components, Route Handlers, or Server Actions, redirection is accomplished via the redirect() function:

jsx
import { redirect } from 'next/navigation';

export default async function ProfilePage({ params }) {
  const session = await getSession();
  if (!session) {
    redirect('/login');
  }
  return <h1>Welcome, {session.user.name}</h1>;
}

5. Dynamic Routing and Segment Matching

Dynamic Segments ([folderName])

Dynamic routes are created by enclosing a folder name in square brackets:

  • Folder path: app/products/[id]/page.jsx
  • Matches: /products/101, /products/abc
  • Parameters are passed to the page component via the params prop:
jsx
export default function ProductPage({ params }) {
  return <h1>Product SKU: {params.id}</h1>;
}

Catch-All Segments ([...folderName])

Matches all subsequent nested path segments:

  • Folder path: app/docs/[...slug]/page.jsx
  • Matches: /docs/intro, /docs/installation/nextjs, /docs/a/b/c
  • params.slug is provided as an array: ['installation', 'nextjs'].
  • Note: Does not match /docs itself.

Optional Catch-All Segments ([[...folderName]])

By wrapping the parameter in double square brackets:

  • Folder path: app/shop/[[...categories]]/page.jsx
  • Matches: /shop, /shop/clothing, /shop/clothing/shoes/sneakers.

Route Groups ((folderName))

To organize route files into logical sections without affecting the URL pathname:

  • Folders wrapped in parentheses (marketing) or (admin) are omitted from the URL path.
  • Example: app/(marketing)/about/page.jsx resolves to /about.
  • Enables defining multiple independent Root Layouts or scoping layouts to specific sub-audiences.

Private Folders (_folderName)

Prefixing a folder with an underscore _lib/ tells the App Router to ignore that directory from routing, allowing developers to safely colocate internal utilities, helper components, or unit tests right alongside routes.