CoachnestCoachnest
Sign InGet Started
Back to course

Next.js 16: The Complete Developer Guide

…
—
Contents
1

What's New in Next.js 16

Reading14mFree
2

Installation, CLI & Your First Project

Reading12mFree
3

Project Structure & Conventions Deep Dive

Reading16m
4

Turbopack — The New Default Bundler

Video18m
5

Configuring TypeScript, ESLint & next.config.ts

Reading14m
6

Chapter 1 — Quiz

Quiz10m
7

App Router Fundamentals

Reading16m
8

Dynamic Routes, Catch-Alls & Type-Safe Params

Reading14m
9

Route Groups & Parallel Routes

Reading16m
10

Intercepting Routes & Modal Patterns

Reading12m
11

Loading, Error & Not-Found UI

Reading12m
12

Chapter 2 — Routing Quiz

Quiz12m
13

Understanding the Server/Client Boundary

Reading18m
14

Choosing When to use "use client"

Reading14m
15

Composing Server & Client Components

Reading14m
16

server-only, client-only & Code Splitting

Reading12m
17

Chapter 3 — Quiz

Quiz10m
18

Fetching Data in Server Components

Reading14m
19

The Next.js 16 Cache Model

Reading16m
20

Revalidation: revalidateTag, revalidatePath & On-Demand

Reading12m
21

Cache Components — Building Reusable Cached Functions

Reading14m
22

Search Params, Cookies & Dynamic APIs

Reading12m
23

Chapter 4 — Quiz

Quiz12m
24

Server Actions From First Principles

Reading16m
25

Forms with useActionState & Progressive Enhancement

Reading14m
26

Optimistic UI with useOptimistic

Reading12m
27

Validation with Zod + Server Actions

Reading12m
28

Chapter 5 — Quiz

Quiz10m
29

Static vs Dynamic vs Streaming

Reading14m
30

generateStaticParams & Pre-Rendering Dynamic Routes

Reading12m
31

Incremental Static Regeneration (ISR)

Reading12m
32

Partial Prerendering (PPR)

Reading16m
33

Edge Runtime vs Node.js Runtime

Reading12m
34

Rendering Strategies Deep Dive

Video22m
35

Chapter 6 — Quiz

Quiz12m
36

Tailwind CSS v4 with Next.js 16

Reading14m
37

CSS Modules, Global Styles & Scoped CSS

Reading10m
38

next/image — Smart, Fast Images

Reading14m
39

Fonts, Icons & Metadata

Reading12m
40

Chapter 7 — Quiz

Quiz10m
41

Middleware Fundamentals

Reading14m
42

Sessions, JWTs & Cookies

Reading16m

Protecting Server Components & Server Actions

Reading12m
44

Chapter 8 — Quiz

Quiz10m
45

Prisma with Next.js — The Production Setup

Reading14m
46

Mutations: Server Actions + Database Writes

Reading12m
47

Route Handlers & REST APIs

Reading12m
48

Chapter 9 — Quiz

Quiz10m
49

Unit & Component Testing with Vitest

Reading12m
50

End-to-End Testing with Playwright

Reading14m
51

Deploying to Vercel

Reading12m
52

Self-Hosting with Docker

Reading14m
53

Production Performance Checklist

Reading12m
54

Final Assessment — Next.js 16 Mastery

Quiz20m
←→navigate lessons
Chapter 8 of 10·Chapter 8 — Authentication & Middleware
Lesson 43 of 54Reading12 min

Protecting Server Components & Server Actions

#Protecting Server Components & Server Actions¶

Middleware is your front door. But you must also re-check auth inside every Server Action and any sensitive Server Component — middleware can be bypassed if a route is misconfigured.

The DRY Helper¶

ts
16 lines
1// lib/auth-guard.ts
2import "server-only";
3import { redirect } from "next/navigation";
4import { getCurrentUser } from "@/lib/auth";
5
6export async function requireUser() {
7  const user = await getCurrentUser();
8  if (!user) redirect("/login");
9  return user;
10}
11
12export async function requireAdmin() {
13  const user = await requireUser();
14  if (user.role !== "ADMIN") redirect("/403");
15  return user;
16}

Using It¶

tsx
7 lines
1// app/admin/page.tsx
2import { requireAdmin } from "@/lib/auth-guard";
3
4export default async function AdminPage() {
5  const admin = await requireAdmin();
6  return <h1>Hi, {admin.name} — you're an admin.</h1>;
7}
ts
8 lines
1// app/courses/actions.ts
2"use server";
3import { requireUser } from "@/lib/auth-guard";
4
5export async function enroll(courseId: string) {
6  const user = await requireUser();
7  return db.enrollment.create({ data: { userId: user.id, courseId } });
8}

Never trust a userId passed from the client. Always read it from the session.

Resource-Level Authorization¶

ts
10 lines
1"use server";
2export async function updateCourse(id: string, data: CourseInput) {
3  const user = await requireUser();
4  const course = await db.course.findUnique({ where: { id }, select: { createdById: true } });
5  if (!course) notFound();
6  if (course.createdById !`== user.id && user.role !==` "ADMIN") {
7    throw new Error("Forbidden");
8  }
9  return db.course.update({ where: { id }, data });
10}

The pattern:

  1. 1Identify the actor (requireUser).
  2. 2Fetch the target resource.
  3. 3Check ownership (or role).
  4. 4Perform the action.

A Permissions Module¶

For complex apps, group rules in one place:

ts
9 lines
1// lib/permissions.ts
2import type { User, Course } from "@prisma/client";
3
4export const can = {
5  editCourse: (u: User | null, c: Course) =>
6    !!u && (u.role =`== "ADMIN" || u.id ==`= c.createdById),
7  deleteCourse: (u: User | null, c: Course) =>
8    !!u && u.role === "ADMIN",
9};
tsx
1 line
1{can.editCourse(user, course) && <EditButton id={course.id} />}

Same module is reused server- and client-side (rules are pure functions — fine to ship).

CSRF Protection¶

Server Actions are immune to traditional CSRF because:

  • Each action is identified by a signed action ID
  • The Origin header is validated by Next.js
  • The request is POST-only and tied to the user's cookie

Route handlers that perform mutations still need their own CSRF checks if you're not using SameSite cookies.

A Final Pattern: Re-fetch After Sensitive Updates¶

After password changes, role changes, or account deletes, rotate the session:

ts
6 lines
1"use server";
2export async function changePassword(input: ChangePassword) {
3  const user = await requireUser();
4  await db.user.update({ where: { id: user.id }, data: { passwordHash: await hash(input.newPassword) } });
5  await createSession({ uid: user.id, role: user.role });   // new JWT, invalidates the old one
6}

Previous

Sessions, JWTs & Cookies

Next

Chapter 8 — Quiz

Use ← → arrow keys to navigate between lessons