Introduction to Next.js
React for production. Routing, server rendering, and full-stack capabilities built in.
Why Next.js
React is a library. Next.js is the framework that makes it production-ready.
// React alone gives you: // - Components and state management // - Virtual DOM diffing // ...and that's it. You still need: // - Routing (which page to show) // - Server rendering (SEO, performance) // - Data fetching patterns // - Code splitting // - Image optimization // - Deployment pipeline // Next.js gives you ALL of that, pre-configured: // ✓ File-based routing (folders = URLs) // ✓ Server-side rendering (SSR) + static generation (SSG) // ✓ Server Components (less JS shipped to browser) // ✓ API routes (full-stack in one project) // ✓ Image optimization (next/image) // ✓ Font optimization (next/font) // ✓ Built-in TypeScript support // ✓ Middleware, redirects, rewrites // ✓ One-command deployment (Vercel) // Create a Next.js project: // $ pnpm create next-app my-app // $ cd my-app && pnpm dev // This site (visualjs.in) is built with Next.js!
App Router
Folders become URLs. Files become pages.
// File-based routing:
// app/
// ├── page.tsx → /
// ├── about/
// │ └── page.tsx → /about
// ├── blog/
// │ ├── page.tsx → /blog
// │ └── [slug]/
// │ └── page.tsx → /blog/my-first-post
// └── layout.tsx → wraps ALL pages
// page.tsx — the page component (required for route to exist):
export default function HomePage() {
return <h1>Welcome to my site</h1>;
}
// layout.tsx — shared wrapper (header, footer, providers):
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<nav>...</nav>
{children} {/* page content goes here */}
<footer>...</footer>
</body>
</html>
);
}
// Dynamic routes — [param] folder:
// app/blog/[slug]/page.tsx
export default async function BlogPost({ params }) {
const { slug } = await params;
// slug = "my-first-post" for /blog/my-first-post
const post = await getPost(slug);
return <article>{post.content}</article>;
}Create a folder → it becomes a URL. Add page.tsx → it becomes a route. Dynamic segments use [brackets].
1 / 2
Server Components
Components that run on the server. Zero JavaScript sent to the browser.
// In Next.js App Router, ALL components are Server Components by default.
// They run on the server and send HTML to the browser.
// Server Component (default — no directive needed):
async function UserProfile({ userId }) {
// This runs on the server — direct database access!
const user = await db.query("SELECT * FROM users WHERE id = $1", [userId]);
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// ✓ Can use async/await directly
// ✓ Can access databases, file system, secrets
// ✓ Zero JS sent to browser for this component
// ✗ Cannot use useState, useEffect, onClick
// Client Component — add "use client" directive:
"use client";
import { useState } from "react";
function LikeButton() {
const [likes, setLikes] = useState(0);
return (
<button onClick={() => setLikes(likes + 1)}>
♥ {likes}
</button>
);
}
// ✓ Can use state, effects, event handlers
// ✓ Can use browser APIs
// ✗ Cannot be async
// ✗ JS is sent to browser (adds to bundle)
// The pattern: Server Components for data + layout,
// Client Components for interactivity (keep them small!)
// page.tsx (Server) → fetches data, renders layout
// └── LikeButton (Client) → handles clicks
// └── CommentForm (Client) → handles inputData Fetching
Fetch data where you need it — directly in components.
// Fetch data in Server Components (simplest pattern):
async function ProductPage({ params }) {
const { id } = await params;
const product = await fetch(
"https://api.example.com/products/" + id
).then(r => r.json());
return (
<div>
<h1>{product.name}</h1>
<p>{product.price}</p>
</div>
);
}
// Parallel data fetching:
async function Dashboard() {
// These run in parallel (not waterfall):
const [user, posts, stats] = await Promise.all([
getUser(),
getPosts(),
getStats(),
]);
return (
<div>
<UserCard user={user} />
<PostList posts={posts} />
<StatsPanel stats={stats} />
</div>
);
}
// Server Actions — mutations from the client:
// app/actions.ts:
"use server";
async function addTodo(formData) {
const text = formData.get("text");
await db.insert({ text, done: false });
revalidatePath("/todos"); // refresh the page data
}
// In a Client Component:
function TodoForm() {
return (
<form action={addTodo}>
<input name="text" placeholder="New todo..." />
<button type="submit">Add</button>
</form>
);
}
// The form submits to the server action — no API route needed!
// Works with and without JavaScript (progressive enhancement)Full Stack
Frontend + backend in one project. Deploy anywhere.
// Next.js is full-stack:
// - React pages (frontend)
// - Server Components (server-rendered UI)
// - Server Actions (mutations)
// - Route Handlers (REST API endpoints)
// - Middleware (auth, redirects)
// All in ONE project, ONE deployment.
// Route Handler (API endpoint):
// app/api/users/route.ts:
import { NextResponse } from "next/server";
export async function GET() {
const users = await db.query("SELECT * FROM users");
return NextResponse.json(users);
}
export async function POST(request) {
const body = await request.json();
const user = await db.insert(body);
return NextResponse.json(user, { status: 201 });
}
// → GET /api/users, POST /api/users
// Middleware (runs before every request):
// middleware.ts (in project root):
import { NextResponse } from "next/server";
export function middleware(request) {
const token = request.cookies.get("session");
if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", request.url));
}
}
export const config = {
matcher: ["/dashboard/:path*"],
};
// Deployment:
// $ pnpm build → optimized production build
// Deploy to: Vercel (zero-config), AWS, Docker, anywhere Node runs
// Vercel: git push → auto-deploys in ~30 seconds
// What you've learned in this course prepares you for Next.js:
// ✓ JavaScript fundamentals → write React components
// ✓ DOM + events → understand what React abstracts
// ✓ Async/await → data fetching in components
// ✓ ES modules → imports/exports everywhere
// ✓ Design patterns → component architecture
// ✓ Build tools → understand the pipeline
// You're ready. Go build something.FAQ
Common questions about Next.js.