Next.js
Rebuild your mental model of the App Router: where each of the four caches bites, what actually crosses the server/client boundary, and why your page went dynamic.
67 concepts412 live tasks
Start practicing freeWhat's inside
App Router Fundamentals
Layouts don't re-render on navigation
template.tsx remounts per navigation; layout.tsx never does
Only page.tsx and route.ts make a URL: everything else is safe to colocate
loading.tsx is sugar for a Suspense boundary around the page
error.tsx catches below itself, not the layout beside it
notFound() and redirect() work by throwing
Segment config: per-route knobs, statically analyzed
Metadata merges shallowly down the tree
Server & Client Components
'use client' marks a module-graph boundary, not a component
Server components render on the server, full stop
'use client' does not mean client-only
What can actually cross the server→client props boundary
Passing server components through client components as children
The RSC payload: what actually goes over the wire
Context is client-only; server data travels by props or cache()
server-only: making the bundler enforce your secrets
Data Fetching Patterns
Fetch where you render: async server components
Identical fetches dedupe within one render pass
Sequential awaits are self-inflicted waterfalls
Suspense boundaries turn slow data into streamed HTML
Start on the server, await on the client with use()
cookies(), headers(), and searchParams make the route dynamic
generateStaticParams prebuilds; dynamicParams decides the rest
Caching Layers
There are four caches, and they don't share a lifetime
The Data Cache and the great fetch default flip
The Full Route Cache: static routes are rendered once, served many
The Router Cache: the browser keeps RSC payloads you can't fully disable
revalidatePath and revalidateTag: purge by location or by meaning
How one revalidateTag call propagates through every layer
'use cache': caching functions and components, not just fetches
Debugging staleness: which layer served this?
Rendering Strategies
Routes are static until something proves otherwise
ISR serves stale and revalidates behind the request
Dynamic rendering isn't slow-by-definition: it streams
Forcing it: dynamic = 'force-static' | 'force-dynamic' and their sharp edges
PPR: one route, static shell, dynamic holes
PPR semantics: what makes it into the shell
Mapping Pages Router instincts to App Router reality
Server Actions & Mutations
Every server action is a public POST endpoint
Forms + useActionState work before hydration
useOptimistic: lie to the UI, let the server correct you
Actions close the loop: mutate, revalidate, redirect (one round trip)
Closed-over values travel to the client (encrypted, but they travel)
Server actions queue: one at a time, in order
Validate the FormData like the hostile input it is
Advanced Routing
[id], [...slug], [[...slug]], and how they rank
Route handlers: API routes with a caching footgun
Middleware runs before everything, so it must do almost nothing
Parallel routes: named slots rendered side by side
Intercepting routes: same URL, modal on soft nav, page on hard nav
Four ways to redirect, four different layers
Route groups can split your app into separate root layouts
Performance & Assets
next/image: on-demand optimization with reserved layout
next/font: zero-request fonts with metric-matched fallbacks
next/script strategies decide when third-party JS gets to hurt you
What actually determines your client bundle size
next/dynamic: split what you can, ssr:false what you must
What <Link> actually prefetches, and when
Streaming SSR + selective hydration: React hydrates what you touch
Deployment Realities
Node vs Edge runtime: a capability trade, not a speed setting
Your routes become functions: cold starts, timeouts, statelessness
Self-hosted ISR breaks quietly without a shared cache handler
Streaming dies at the first buffering proxy
NEXT_PUBLIC_ is inlined at build: the build-once problem
What Next tells the CDN: reading the Cache-Control it emits
Version skew: old clients, new server, broken actions
output: 'standalone' (the Docker-shaped build)

