From Zero
to Next.js
Web evolution, core concepts, rendering strategies, routing, hydration — all in one place. Visual-first, no textbook walls.
How the Web Evolved
Six eras that brought us from simple HTML files to full-stack React apps. Click any card to expand.
🌐 Static Web
Basic HTML pages with no interaction beyond hyperlinks. Every visitor saw the exact same page.
Think: Tim Berners-Lee's original site. Pure HTML, no CSS, no scripts. A document viewer — nothing more.
⚡ Dynamic Interactions
XHR / Ajax lets the browser talk to the server in the background — updating parts of the page without a full reload.
XMLHttpRequest was "Web 2.0" magic. Pages felt responsive. JavaScript became essential.
🗄️ Server-Generated Content
Servers produce custom HTML per user — reading databases to personalise every response.
PHP, Rails, Django — server reads DB → renders HTML → sends full page. Every request = fresh server render.
📱 Single Page Apps
HTML loads once, then JS dynamically swaps content. Browser becomes the rendering engine — fluid, app-like.
Angular (2010) pioneered this. Server just returns JSON. Browser handles all rendering — fast UX, but bad SEO.
⚛️ React
Component-based UI + Virtual DOM. Surgically re-renders only what changed. Real-time updates, zero page reload.
Declarative UI. State changes re-render only the affected component tree. Composable and efficient.
▲ Next.js
The best of all worlds — SSR for fast loads, CSR for interactivity, file routing, SEO, and image optimisation, all out-of-the-box.
Next.js wraps React and solves routing, SSR, API routes, image & font optimisation — zero config.
What is Next.js?
Think of Next.js as React with superpowers. React is great, but you have to set up a lot of things yourself. Next.js comes with all those things already built in — so you can just focus on building your app.
Routing
Just create a file and Next.js makes it a page automatically. No extra setup.
Rendering
You can choose — build the page on the server, or in the browser. Your call.
Data Fetching
Easily load data from APIs or databases. It even saves the result so you don't fetch it again and again.
Server Components
Some parts of your page run on the server only. No JavaScript is sent to the user's browser for those parts.
Optimisation
Images load faster, fonts don't flash, scripts don't slow you down — Next.js handles it all.
SEO Friendly
Google can read your page content properly because the HTML is ready before the browser even runs JavaScript.
Rendering Environments
To grasp the capabilities of Next.js, one must start at the core — rendering environments. There are two primary environments: the server and the client.
Rendering is the process of converting code into a visual and interactive display that users can view and interact with within a web browser. This process begins when a browser requests a webpage and ends with the server’s response, culminating in the rendered application the user interacts with.
There are two primary rendering environments: server and client. Server-side rendering (SSR) means that the assembly of the webpage happens mainly on the server, while Client-side rendering (CSR) assembles mainly on the client’s browser. A well-optimized web application utilizes a combination of both methods, leveraging the strength of each.
While React supports both, it lacks built-in SSR. This makes Next.js a go-to choice for developers, as it offers robust support for both SSR and CSR. With Next.js, we can specify rendering granularity down to the component level, choosing if it should be server-rendered, client-rendered, or a combination of both.
Explore the visual step-by-step differences below between client-rendered and server-rendered environments.
Client Sends Request
The user's browser sends a request to the website's server when the user visits a website.
Server Receives Request
The server receives the request from the browser and prepares to construct the page.
Server Fetches Data & Files
The server fetches the required data (from databases or APIs) and files needed to construct the complete webpage.
Server Renders HTML
The server compiles the data and runs React components to render the webpage into static HTML.
Server Composes Response
The server has finished rendering the webpage to HTML and wraps it up inside a completed response.
Server Sends Response
The server sends the fully rendered HTML webpage back to the user's browser.
Browser Receives Response
The user's browser receives the fully built HTML response, showing content instantly.
Display Website
The user's browser displays the fully rendered page to the user (which then hydrates in the background).
Client-Side Rendering (CSR)
Client-side rendering is key to modern dynamic single-page applications. The server delivers a barebones HTML file, and the client browser runs JavaScript to construct the full page and enable interactivity.
Think of a website that offers a highly interactive, seamless, and dynamic user experience like YouTube and Airbnb. Client-side rendering (CSR) plays a significant role in making such experiences possible.
In Next.js, client-side can be implemented explicitly through client components, an opt-in feature that allows developers to designate specific components to be rendered on the client.
In a later lesson, we’ll dive into the details of client components, but for now, know that you can define a client component as you would a regular React component with a 'use client' directive. This directive specifies that the component and its children components should be rendered on the client side.
Interactive Code Sandbox
Click the interactive toggle box on the right to see the live rendering and how React updates state inside the client.
'use client' import React, { useState } from 'react' export default function Page() { const [toggle, setToggle] = useState<boolean>(false) return ( <div onClick={() => setToggle(!toggle)}> {toggle ? 'True' : 'False'} </div> ) }
Dynamic Single Page Application (SPA) Demo
Simulate how client-side applications fetch raw JSON data and update the UI instantly without reloading the entire page.
Server-Side Rendering (SSR)
SSR compiles dynamic pages directly on capable server infrastructure. This improves speed, SEO crawlability, and offloads rendering work from the client hardware.
While client-side rendering allows websites to be dynamic and interactive, constructing and loading the page all on the client’s hardware can be an expensive endeavor. A slow internet connection or slow client hardware can compound the wait time for the user, who is busy staring at nothing as the browser assembles the webpage.
In server-side rendering (SSR), the webpage is assembled on the server. Offloading the rendering to the server leverages the more capable server infrastructure, reducing the load on the client’s hardware.
Server-side rendering is ideal for web applications that need a lot of data fetching, search engine optimization (SEO), and speed. By moving the fetching requests closer to the database, developers reduced the latency of these requests. Sending fully rendered pages also means users can view them immediately when visiting a website, regardless of their hardware’s capabilities. The rendered pages can then be crawled and indexed by search engine bots, leading to better SEO.
By default, Next.js renders components on the server side. You can define a React component without additional configurations, as Next.js automatically handles the server-side rendering.
Within server-side rendering itself, Next.js offers three distinct approaches: static rendering, dynamic rendering, and streaming. In a later lesson on Server Components, we will delve deeper into these subsets and their specific applications.
At this stage, while the page is visible and contains elements like buttons and form fields, they are not fully interactive. In a sense, it is like a fresh first layer of paint on our page. In the next exercise, we’ll be discussing what comes after to make the web application interactive.
Next.js SSR Subsets
Next.js offers three core environments under Server-Side Rendering. Click each card to see the details.
Static Rendering
Build Time (Once)HTML is rendered once during project build. The result is cached and served...
Dynamic Rendering
Request Time (Every visit)HTML is generated on the server for each user request. Best for personalize...
Streaming
Progressive loadingThe server renders pages in chunks. Highly critical HTML parts load first, ...
Static Rendering (Build Time (Once))
HTML is rendered once during project build. The result is cached and served instantly to everyone via a CDN.
SEO Bot Indexing & Paint Layer Analogy
SSR outputs static HTML first, providing instant visibility to users and search engines.
Everything is painted on the screen right away, but not yet interactive:
Starting a New Project
You don't have to set up a Next.js project from zero. Just run one command in the terminal and it asks you a few questions, then builds the whole project for you automatically. It's like pressing a “new project” button.
The App Router — Pages from Folders
In Next.js, you don't need to write any code to set up your pages. Just create a folder with a file inside it, and that automatically becomes a page on your website. The folder name becomes the URL. Click on the files below to see how it maps.
Route Map
Simple Rule: Folder name = URL address. Put a page.tsx inside the folder = anyone can visit that page. No page.tsx = page not found (404 error).
What is Hydration?
When SSR sends you a ready-made page, it looks good — but buttons don't work yet. Hydration is when JavaScript loads and makes everything clickable. Think of it like: the page is a statue, hydration gives it a heartbeat. Click each step below.
Receive Files
A client device receives a fully rendered HTML page. It also receives a bundle of JavaScript files, and any extra data needed to make the page is sent.
Represent Server DOM
The fully rendered HTML page received from the server is parsed and represented as a standard DOM tree in the browser.
Construct Virtual DOM
Once the client's device receives the HTML page and the JavaScript bundle, React initializes and starts constructing a Virtual DOM tree.
Virtual DOM Ready
The Virtual DOM structure is successfully built in client-side memory, reflecting the expected React component structure.
Locate Attachments
React parses the Virtual DOM to locate where dynamic events (like onClick, onSubmit) and other interactivities should be attached.
Match DOM Elements
React walks the real Server DOM tree to locate the actual matching physical elements corresponding to the event attachment points.
Reconciliation Check
React compares the constructed Virtual DOM with the actual Server DOM nodes to ensure consistency. If there is a mismatch, a hydration warning is thrown.
Attach Interactivity
React attaches the event handlers to the corresponding real DOM nodes. The application starts listening to events from the elements.
Page Interactive
The HTML page is now fully interactive. Click handlers are bound, input fields update, and any buttons on the screen can be clicked.
CSS Modules — Styling Without Mess
Normally, if two components both have a CSS class called .btn, they crash into each other and break the style. CSS Modules fix this — each component gets its own private styles that never mix with anyone else's. Just name your file with .module.css at the end.
❌ Without CSS Modules GLOBAL
/* Applies EVERYWHERE */ .btn { background: blue; } /* Another component's .btn */ .btn { background: red; /* 💥 CONFLICT! */ }
.btn style applies to the whole app — any component that uses .btngets affected, even if you didn't want that✅ With CSS Modules SCOPED
/* Button.module.css */ .btn { background: blue; } import styles from './Button.module.css' export function Button() { return <button className={styles.btn}>Click!</button> }
.btn to something like .btn_x7a3k so it only applies to thiscomponent — never anyone else'sLevel 1 — Core Next.js (App Router)
A visual guide to structuring routes, layouts, links, and pages. Learn how Next.js translates the folder structure directly into your web application URL system.
🎓 What You Will Learn to Build
By the end of this level, you should be able to create a fully-routed, cohesive site with a shared navigation layout and dynamic segments:
1. The App Folder & Route Segments
The app/ folder is the heart of Next.js routing. Every folder nested inside app/ becomes a Route Segment in the URL path.
💡 Click on any file to inspect how the route structures mapping works.
How it works
The main entry page of your website. Next.js maps the root folder directly to the homepage.
export default function HomePage() {
return <h1>Home Page</h1>;
}Rule: Folder name = Route Segment. The page.js file defines the actual screen content the user sees. Without a page.js file inside a folder, that path returns a 404 error.
2 & 3. page.js & layout.js
Every route needs a page.js. To avoid repeating shared UI like Navbars and Footers on every page, Next.js uses layout.js to wrap nested files automatically.
layout.js renders shared structure. Next.js passes the page component into the layout as the { children } prop, so the navbar and footer stay in place.🏠 Home Page content renders here
4. Nested Layouts
Next.js allows layouts to be nested. Layouts in subfolders act as wrappers around pages in their directory, nested inside the outer root layout.
Visual Nesting Hierarchy
5 - 8. Route Types (Static & Dynamic)
Next.js supports static routing, dynamic segments using brackets [slug], and catch-all routes [...slug] to handle flexible page configurations.
⚡ Dynamic Routes Parser ([slug])
Select or type a slug to observe how Next.js routes it inside app/blog/[slug]/page.js:
export default function BlogPost({ params }) {
// params = { slug: "react" }
return <h1>{params.slug}</h1>;
}🗂️ Catch-All Routes Parser ([...slug])
Catch-all folders catch all subfolders. Type a slash-separated pathway to analyze the results:
// params.slug represents sub-segments
params = {
slug: ["react","hooks","useState"]
}9 & 10. Route Groups & Navigation
Route Groups group folders together without impacting URLs. Next.js <Link> enables Single Page Application navigation without full page reloads.
📁 Route Groups (marketing)
Parentheses folders like (marketing) or (dashboard) tell Next.js to ignore this folder name when creating URL links.
/about works perfectly. Visting /marketing/about returns a 404.🚀 Transition Sandbox: Link vs Anchor
Increment the counter state, then route between home/about pages using standard anchor tags vs Next.js Link component.
11. Mini Blog Project Structure
Below is the finalized file hierarchy and website router map for our level 1 blog application, incorporating navigation wrappers and dynamic subpaths.
📍 Application Sitemap Map
Next.js matches paths like /blog/react automatically by injecting the string “react” into params.slug on the page template.
Level 1 Mastery Checklist
Check off items as you master them to track your learning progress. Try to build the mini-blog from memory!
Level 2 — Rendering System (Modern Next.js)
One golden rule governs modern Next.js development: Where does this code run? Server or Browser? Learn to architecture client interactivity on top of lightning-fast server infrastructure.
🎓 Level 2 Curriculum Overview
Master the App Router rendering system across 6 comprehensive modules:
1. What is Rendering?
Rendering is the process of Next.js taking your React components and translating them into HTML elements that browsers can parse and show on the screen.
Step 1: User requests a page (e.g. clicks a link or enters the URL).
2 - 6. React Server Components (RSC)
Server Components run exclusively on the server, offloading computations from user hardware. In Next.js, every component is a Server Component by default.
2. Default Server Component
No special keywords required. Standard code runs natively on the backend.
export default function Home() {
return <h1>Hello Server</h1>;
}3. Async Server Component
Next.js allows components to be declared `async` to await database queries or APIs directly.
export default async function Page() {
const res = await fetch('...');
return <div>Data Ready</div>;
}4. Fetching Data in Server Components
Click a database target to simulate server fetching. Notice how simple the data request flows directly inside the component body:
const res = await fetch(
'https://api.com/users'
);
const data = await res.json();[
{
"id": 1,
"name": "Leanne Graham",
"email": "Sincere@april.biz",
"company": "Romaguera-Crona",
"city": "Gwenborough"
},
{
"id": 2,
"name": "Ervin Howell",
"email": "Shanna@melissa.tv",
"company": "Deckow-Crist",
"city": "Wisokyburgh"
}
]5. Reading Databases Directly
Since Server Components run in the secure backend environment, you can query database engines directly. No intermediate API endpoints required!
User.find()Credentials: process.env.DB_URI (Hidden from browser)import { db } from "@/lib/db";
export default async function Dashboard() {
const users = await db.users.findMany(); // Runs directly on Server!
return <div>Loaded {users.length} users.</div>;
}6. Server Components Limitations Matrix
An interview favorite. Understand what Server Components are natively allowed to execute vs what breaks.
7 - 12. React Client Components
Client Components allow you to add interactivity to your application. They run in the browser and are hydrated after loading.
7. The "use client" Boundary
Add the `"use client"` string directive at the very top of a file. This declares a boundary, informing Next.js that this component and any imports it makes will run in the browser.
"use client";
import } useState } from "react";
export default function Counter() { ... }8. useState in Action
Allows dynamic UI reactivity based on interactions. Test the client widgets:
const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>10. Event Handlers
Capturing user gestures directly in browser (e.g. typing, hovering, submitting):
Captured Events: onMouseEnter, onChange, onSubmit
9. useEffect Side Effects
Running side effects in the client (updating DOM, starting intervals, window listeners). Test the effect tasks:
11. Interacting with Browser APIs
Only Client Components can access browser APIs like `window`, `document`, and `localStorage` because they execute inside the browser sandbox.
useEffect(() => {
// Safe to access browser APIs inside client side hooks
const pref = localStorage.getItem('theme_preference');
setPref(pref);
}, []);12. Client Components Limitations Matrix
Avoid heavy calculations, and never include credentials or secret keys in Client Components. They are compiled into JS bundles and sent directly to the client browser!
13 - 15. Server and Client Composition
Next.js allows you to nest Client Components inside Server Components. You fetch data securely on the server and pass it down as props.
13. Passing Props Across the Boundary
Props passed from Server Components to Client Components must be serializable (e.g. JSON strings, arrays, basic objects). Databases connections or classes cannot cross this boundary:
14. Mixing Components
Place the interactive client segments in isolated leaves. Keep parent containers running as Server Components.
import Search from '@/components/Search';
export default async function Page() {
const data = await fetchUsers();
return (
<main>
<h1>Directory</h1>
<Search initialUsers={data} />
</main>
);
}15. Composition Pattern
To nest a Server Component inside a Client Component, pass it as the children prop. This ensures the Server Component is compiled before reaching the browser.
"use client"
export default function ClientWrapper({ children }) {
return (
<div className="interactive-layout">
{children} {/* Server components render fine here */}
</div>
);
}16 - 17. Server vs Client Component Choice
Failing to choose the correct component environment leads to runtime errors or performance penalties. Use this step-by-step decision tool.
16. Checklist Cheat Sheet
17. Choosing the Right Component Builder
Click options to evaluate the environment selection tree:
12. User Directory Project Structure
Below is the finalized file hierarchy and visual components map for our Level 2 user directory application, integrating Server and Client components.
📍 Application Components Map
Data fetches securely on the Server Component (page.js) and flows down via serializable props to the interactive Client Components.
🖥️ Nearly Expected Website Sketch
The final application layout renders the dynamic search filter and active widgets sequentially:
--------------------------------
User Directory
Search: ___________
------------------------
Leanne Graham
Ervin Howell
Clementine Bauch
...
------------------------
Counter: 0
[+]
------------------------
[Open Modal]
------------------------
Dark Mode Toggle
--------------------------------🚀 My recommendation for how we proceed
Don't build the whole thing at once. Treat this like a guided Next.js course.
- Project setup
- Understand the folder structure
- Build
app/page.js - Convert it to an async Server Component
- Fetch users from the API
- Render the user list
- Understand why the logs appear in the terminal instead of the browser
Level 2 Practice Checklist
Check off items as you master them to track your learning progress. Try to build the user directory simulator app from scratch!
⚡ Quick Cheatsheet
Everything from Part 1 + Part 2 + Part 3 in one glance