← Knowledge Base
Enterprise engineering · 12 weeks · 20–30 minutes/day

Next.js App Router Master Class

A production-grade study plan for developers with a React and JavaScript foundation who want to master React Server Components, Server Actions, TypeScript, secure APIs, and modern deployment architecture.

App RouterRSCServer ActionsTypeScriptEnterprise

Architecture & enterprise project structure

Modern Next.js applications need an explicit separation between Server Components, Client Components, Server Actions, and Route Handlers. This typed structure is the reference architecture used throughout the curriculum.

my-enterprise-app/
├── app/
│   ├── (auth)/login/page.tsx
│   ├── (auth)/layout.tsx
│   ├── (dashboard)/dashboard/
│   │   ├── @analytics/page.tsx
│   │   ├── @metrics/page.tsx
│   │   ├── error.tsx · loading.tsx · page.tsx
│   │   └── layout.tsx
│   ├── api/v1/webhooks/route.ts
│   ├── global-error.tsx · layout.tsx
│   ├── page.tsx · providers.tsx
├── actions/          # Server Actions
├── components/       # ui, server, client
├── lib/              # auth, db, validators
├── proxy.ts · middleware.ts
├── next.config.ts · tsconfig.json · package.json
Boundary rule
Keep secrets and database utilities on the server. Add 'use client' only where browser APIs, hooks, or event handlers require it. Serialize props across the boundary.

The 12-week roadmap

Weeks 1–3 · Level 1App Router, RSC boundaries, layouts, route groups, streaming, loading UI, and error isolation.
Weeks 4–6 · Level 2Data fetching, request memoization, cache tags, revalidation, Server Actions, and optimistic UI.
Weeks 7–9 · Level 3Proxy/middleware, sessions, security headers, Route Handlers, CORS, and signed webhooks.
Weeks 10–12 · Level 4Web Vitals, image/font/script optimization, standalone containers, Playwright, Vitest, and Turbopack.

Daily rhythm: spend 5–10 minutes on the architecture concept, then 15–20 minutes implementing one typed drill. On Day 7, complete the weekly quiz before reviewing the answers.

Weeks 1–3 · Level 1

App Router & component architecture

Build a reliable foundation in the RSC paradigm, file-system routing, nested layouts, loading UI, streaming, and boundary isolation.

Module 1.1 · Server vs. Client Component boundaries

  • RSCs are the default in app/; they execute on the server without shipping their component JavaScript to the browser.
  • Use 'use client' for state, effects, event listeners, and browser APIs. Keep server-only modules protected with import 'server-only'.
  • Practice: typed Counter, a client CardWrapper that accepts Server Components as children, a server-rendered dashboard, server-only database utilities, and serialized UserDTO props.
// components/client/counter.tsx
'use client';
import { useState } from 'react';

export function Counter({ initialCount }: { initialCount: number }) {
  const [count, setCount] = useState(initialCount);
  return ;
}

Module 1.2 · Advanced routing and nested layouts

  • Layouts preserve state across sibling navigation; route groups organize code without changing the URL.
  • Practice root metadata and fonts, dashboard layouts, typed dynamic segments such as [category]/[productId], catch-all docs routes, and parallel slots @analytics and @metrics.

Module 1.3 · Streaming, loading UI, and error isolation

  • loading.tsx creates a Suspense boundary for streaming fallbacks; error.tsx isolates runtime failures and provides reset().
  • Practice route skeletons, granular Suspense around slow analytics, global-error.tsx, and not-found.tsx.
Weekly review
  1. What happens when server-only database code is imported into a Client Component?
  2. Why does a layout retain state during sibling navigation?
  3. Does 'use client' automatically make every child component client code?
  4. How does loading.tsx enable streaming?
  5. Why must error.tsx be a Client Component?

Graduation project · Product Inventory Catalog

Build a Tailwind dashboard with a root layout, a dashboard sidebar, parallel analytics and metrics routes, a Suspense-streamed slow widget, and an isolated mock database error boundary. Evaluation: architecture 40%, routing 30%, error handling 30%.

Weeks 4–6 · Level 2

Data fetching, caching & Server Actions

Learn the difference between request memoization and persistent Data Cache behavior, then build type-safe mutations with secure invalidation.

Module 2.1 · Fetching and cache strategy

  • Use next.revalidate for time-based freshness, next.tags for targeted invalidation, and cache: 'no-store' for live stock or other request-time data.
  • Use React cache() to deduplicate a database read within one render pass; use segment exports such as revalidate = 300 and dynamic = 'force-dynamic' intentionally.
export async function getProductById(id: string) {
  const res = await fetch(`/api/products/${id}`, {
    next: { tags: [`product-${id}`, 'products'] },
  });
  if (!res.ok) throw new Error('Failed to fetch product');
  return res.json();
}

Module 2.2 · Server Actions and form mutations

  • Server Actions are secure server-side functions invoked by forms or client transitions, but their inputs still require authentication, authorization, and schema validation.
  • Practice Zod validation with useActionState, optimistic todo updates with useOptimistic, revalidatePath, and pending states with useTransition.
'use server';
import { revalidateTag } from 'next/cache';
import { z } from 'zod';

const Product = z.object({ title: z.string().min(3), price: z.number().positive() });
export async function createProductAction(_: unknown, formData: FormData) {
  const result = Product.safeParse({
    title: formData.get('title'),
    price: Number(formData.get('price')),
  });
  if (!result.success) return { error: result.error.flatten().fieldErrors };
  // Authenticate, authorize, then insert into the database.
  revalidateTag('products');
  return { success: true };
}
Weekly review
  1. How do Request Memoization and Data Caching differ?
  2. How does revalidateTag('products') affect tagged fetches?
  3. What security checks belong inside every exported Server Action?
  4. What does useActionState contribute to a form?
  5. What becomes stale after revalidatePath('/dashboard')?

Graduation project · Real-Time Task & Inventory Manager

Build tagged data fetches, a Zod-validated inventory mutation, optimistic item addition, and tag revalidation. Evaluation: data integrity 40%, caching strategy 30%, user experience 30%.

Weeks 7–9 · Level 3

Auth, proxy/middleware & API integration

Protect enterprise routes, propagate tenant context, handle Web Platform requests, and verify incoming webhooks without weakening the boundary.

Module 3.1 · Session guards and security headers

  • Use proxy/middleware before route resolution to inspect sessions, redirect unauthenticated dashboard requests, inject tenant headers, and apply security response headers.
  • Read and set cookies with cookies(); use httpOnly, secure, sameSite, an explicit path, expiry, and server-side session validation.
export function middleware(request: NextRequest) {
  const token = request.cookies.get('session_token')?.value;
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}
export const config = { matcher: ['/dashboard/:path*', '/admin/:path*'] };

Module 3.2 · Route Handlers and webhooks

  • Practice typed GET query handling, Zod-validated POST bodies, raw-body HMAC signature verification, CORS response headers, and a streaming ReadableStream.
  • Webhook verification must consume the exact raw request text before parsing; byte-for-byte fidelity is required for the signature check.
Weekly review
  1. What runtime constraints apply to middleware?
  2. Why must a webhook verify the raw body?
  3. How do headers injected by middleware reach a Route Handler?
  4. How does a middleware redirect differ from a Server Action redirect?
  5. How does httpOnly protect a session cookie from XSS access?

Graduation project · Multi-Tenant SaaS Auth & Webhook Gateway

Protect dashboard and admin routes, inject tenant context, validate payment webhooks, implement an HttpOnly session flow, and enforce role-based permissions. Evaluation: security 40%, middleware precision 30%, API standards 30%.

Weeks 10–12 · Level 4

Performance, testing & enterprise deployment

Finish with measurable Core Web Vitals, lean production images, dependable end-to-end coverage, and a modern development toolchain.

Module 4.1 · Web Vitals and built-in optimizations

  • Use next/image with dimensions or fill and correct sizes to reduce CLS; use next/font for optimized fonts and next/script strategies for third-party code.
  • Use next/dynamic with ssr: false for browser-only heavy charts and choose static or dynamic segment configuration deliberately.
const HeavyChart = dynamic(() => import('./heavy-chart'), {
  loading: () => <p>Loading Chart Module...</p>,
  ssr: false,
});

Module 4.2 · Standalone deployment and testing

  • Configure output: 'standalone' and use a multi-stage Node 20 Alpine container: install, build, copy .next/standalone and .next/static, then run node server.js.
  • Write Playwright E2E assertions for dashboard rendering and streamed widgets, Vitest tests for Server Action validation, and a Turbopack dev script.
const nextConfig: NextConfig = {
  output: 'standalone',
  images: { remotePatterns: [{ protocol: 'https', hostname: 'images.example.com' }] },
};
Weekly review
  1. What does standalone output generate?
  2. Why does next/image reduce CLS?
  3. When should afterInteractive or lazyOnload be used?
  4. Why can heavy client components use ssr: false?
  5. How does Suspense streaming improve LCP?

Graduation project · Analytics Engine & Containerized System

Target LCP below 1.2s and CLS below 0.01, ship a multi-stage standalone container, write a comprehensive Playwright suite, and configure Turbopack. Evaluation: Web Vitals 40%, DevOps 30%, testing 30%.

Master capstone · E-Commerce & Fleet Analytics Engine

Combine every level into a high-throughput enterprise system with strict boundaries, secure multi-region routing, resilient data mutations, and an observable deployment.

ArchitectureApp Router with clean Server/Client separation and zero server-secret leakage.
SecurityMulti-region middleware authentication, tenant header routing, HttpOnly sessions, and secure response headers.
DataZod-validated Server Actions with precise tag invalidation and no unnecessary origin calls.
DeliveryMulti-stage standalone build with a production footprint under 150MB.
Evaluation dimensionWeightTarget
RSC boundary hygiene25%No server-secret leaks; clean client state boundaries
Data fetching & caching25%Precise revalidateTag; no needless origin calls
Auth & middleware security25%HttpOnly validation and secure response headers
Performance & deployment25%LCP < 1.2s, CLS < 0.01, image < 150MB

Daily execution system

1 · One drill per day
Implement the typed TypeScript example in a local project instead of rushing ahead.
2 · Day 7 review
Work through the weekly quiz from memory before reading the explanations.
3 · Weekend synthesis
Turn the five drills into that level's graduation mini-project.
4 · Verify the boundary
Ask where code executes, what is serialized, what is cached, and who is authorized.