Next.js
Next.js is the React meta-framework most job postings assume you already know, so interviews go straight to its App Router, rendering modes, and server-side primitives. This tree covers the Next-specific implementation of ideas React itself only sketches.
on this pageshowhide
guide
overview
~1 minNext.js is the React framework that decides, for every route, where code runs — server or browser — and when its output is produced: at build time, again after a revalidation window, or per request. Interviewers probe it because those decisions surface as real bugs — stale data after a write, a whole site that quietly went dynamic, a secret that shipped to the client, an admin check that lived only in the UI. A strong answer names the file or directive behind a choice and the layer where its failure would show. The hub follows the life of a request. [Routing and layouts](/topics/fe-nextjs-routing) is the route tree that everything else hangs off. [Rendering modes](/topics/fe-nextjs-rendering) decides when each route's HTML is produced and how it streams. [Server Components](/topics/fe-nextjs-rsc) draws the line between server and browser code, and [Server Actions](/topics/fe-nextjs-server-actions) is how the browser writes back across it. [Data fetching and caching](/topics/fe-nextjs-data-caching) explains why what you see may not be what the database holds. [Middleware and API routes](/topics/fe-nextjs-middleware) covers the code that runs before a route and the endpoints outside it, and [optimization and deployment](/topics/fe-nextjs-optimization-deployment) is where images, fonts, bundles and hosting targets meet production. Junior rounds check conventions: which file makes a URL, what `'use client'` is for. Senior rounds turn into diagnosis — which cache holds the stale copy, why one call in a layout made every route dynamic, where authorization has to live when middleware already checked a cookie. Learn the route tree and the server/client split first; rendering and caching only make sense on top of them, and actions, middleware and deployment build on all three.
primer
### The filesystem is the router In the App Router, folders under `app/` are URL segments and a handful of reserved file names give a segment its behaviour: a page, a layout that wraps it, a loading state, an error boundary, an HTTP endpoint. Nesting folders nests UI, and many caching and streaming questions turn out to be about which segment the code sits in. ### Server by default, client by opt-in Components in `app/` are **Server Components**: they run on the server, can await data directly, and add nothing to the browser bundle. A `'use client'` directive marks the entry point of browser code, and everything that module imports comes along. Where that line sits decides bundle size, which props must be serializable, and what a user can read in the page source. ### A route is static until something makes it dynamic Next.js prefers to prerender. A route becomes per-request when code in any part of it — the page or any layout above it — reads something only a request can supply, such as cookies, headers or search params, or opts out explicitly. The decision belongs to the whole route, not the component that made the call, so one line in a shared layout can change the build output of a whole site. ### Caching is layered, and invalidation is your job Between a data source and the screen sit several caches, on the server and in the browser, each with its own lifetime and its own way to be cleared. A successful write says nothing about what users see next: the code that writes must tell Next.js which cached data is now wrong, by path or by tag. Good answers name the layer, not "the cache". ### Every server entry point is public Server Actions, route handlers and middleware are all reachable by anyone who can send an HTTP request, whatever the UI shows. Hiding a button, gating a URL prefix or typing a parameter enforces nothing at runtime. Validation and per-resource authorization belong in the code that reads or writes the data. ### Streaming turns waiting into structure Suspense boundaries, including the one a `loading` file creates, let the server send the parts of a page that are ready and fill in the slow parts later. Where you place a boundary and where you place an `await` decide what the user sees first.
- App Router
- The routing system built on the app directory, where folders define URL segments and special files define pages, layouts and states. It replaced the older pages directory as the recommended model.
- Route segment
- One folder level in the app directory, corresponding to one part of the URL path. Layouts, loading states and segment config attach to a segment and apply to everything beneath it.
- Server Component
- A React component that renders only on the server, may be async and access server resources directly, and sends rendered output rather than its code to the browser.
- Client Component
- A component from a module marked with the use client directive, or imported by one. It is usually prerendered on the server, then hydrated so hooks and event handlers work.
- RSC payload
- The serialized result of rendering Server Components: the rendered tree plus props for Client Components. Client-side navigation fetches this instead of a full HTML document.
- Server Action
- An async function marked with the use server directive that client code can call. Next.js exposes it as a POST endpoint, so it must validate and authorize its own input.
- Static rendering
- Producing a route's output ahead of any request, at build time or during revalidation, and serving the stored result to every visitor.
- Dynamic rendering
- Rendering a route on the server for each incoming request, needed when the output depends on who is asking or on request data such as cookies.
- Incremental Static Regeneration
- Serving a prerendered route and regenerating it after a staleness window or an explicit invalidation, so static pages can change without a full rebuild.
- Data Cache
- The persistent server-side store of fetch results, reused across requests and, depending on the host, deployments, until its entries are revalidated.
- Router Cache
- The in-browser memory of route segments the user has already visited or prefetched, used to make back navigation and repeat visits instant.
- Partial Prerendering
- A rendering model that serves a route's static shell immediately and streams its dynamic holes into it within the same response.
- Middleware
- A single root-level function that runs before routing for matched requests and can redirect, rewrite, or modify headers and cookies.
- Route handler
- A route file exporting functions named after HTTP methods, turning its folder's path into an HTTP endpoint; the App Router successor to API routes.
- Edge Runtime
- A lightweight JavaScript runtime exposing Web-standard APIs but not Node.js built-ins, so libraries that need the file system or raw sockets cannot run there.
Trace one request. **Middleware** runs first for any path its matcher selects and may redirect, rewrite or set headers before a route is chosen. The router then resolves the URL against the `app/` tree and composes the route: the root layout, the layouts nested beneath it, and finally the page. If the route was prerendered and its stored output is still fresh, it is served as it is; otherwise the server renders it. Rendering runs the Server Components top down, reading data through `fetch` or direct queries, each read possibly answered by the Data Cache. Where a Client Component appears, the server normally renders its HTML too and records its props in the RSC payload so the browser can hydrate it. Suspense boundaries let finished parts stream ahead of slow ones. After the first load the browser keeps the app alive. Links prefetch and navigate by fetching RSC payloads, which the Router Cache remembers. When the user submits a form wired to a **Server Action**, the action runs on the server, performs its write, and revalidates the paths or tags it touched; the response carries fresh output for the current page, and the invalidated entries are rebuilt the next time something asks for them. **Route handlers** sit beside this loop for callers that are not your own UI — webhooks, mobile clients, third parties. ```tsx // app/posts/page.tsx — a Server Component: its code never reaches the browser import { LikeButton } from './like-button' // this module starts with 'use client' export default async function Posts() { const posts = await fetch(API_URL, { next: { revalidate: 300, tags: ['posts'] } }).then(r => r.json()) return posts.map(p => <article key={p.id}>{p.title}<LikeButton id={p.id} /></article>) } // app/posts/actions.ts 'use server' export async function like(id: string) { const user = await requireUser() // authorization lives in the action await db.addLike(user.id, id) revalidatePath('/posts') // the write is not visible until a cache is told } ``` Three sections meet in those lines: the fetch options belong to caching, the `id` prop crossing into `LikeButton` is serialized into the payload, and the action is a public endpoint that must check its caller and invalidate what it changed.
- Routing and Layouts →
The route tree every other section refers to: file conventions, dynamic segments, layouts and how navigation moves through them.
- Server Components →
The server and client split, which decides where code runs, what reaches the bundle and what props must survive serialization.
- Rendering Modes →
When a route's output is produced — build, timer or request — and how streaming shapes what appears first.
- Data Fetching and Caching →
The cache layers behind stale-data bugs, and which one to invalidate; builds directly on rendering modes.
- Server Actions →
The write path back to the server, where revalidation and security posture meet in one function.
- Middleware and API Routes →
Code before the route and endpoints outside it, and choosing between middleware, route handlers and actions.
Putting
'use client'at the top of a page to make one button interactive, which drags the whole subtree into the bundle; see Composition Across the Boundary.Answering a stale-data question with "clear the cache" instead of naming the layer — request memoization, Data Cache, Full Route Cache or Router Cache — and how that one is invalidated.
Assuming a Server Action refreshes the page's data because the write succeeded; without a path or tag revalidation the cached output stays as it was.
Treating a middleware cookie or role check as authorization; it gates a URL family, while per-record access must be enforced where the data is read or written.
Calling cookies or headers in the root layout for a small feature and discovering every route, marketing pages included, now renders per request.
Describing time-based revalidation as a scheduled rebuild; regeneration happens only when a request arrives after the window, and that visitor still gets the stale copy.
Quoting caching defaults without a version: whether a plain
fetchis cached changed in Next.js 15, and many tutorials describe the older behaviour.Reading a secret from
process.envin a Client Component and expecting it to work; onlyNEXT_PUBLIC_variables are inlined, and those are public by design.
This guide assumes the App Router on Next.js 15 or 16. Several questions turn on what changed along the way, because codebases and tutorials from earlier releases are everywhere: - **Next.js 13** introduced the `app` directory, Server Components and nested layouts; 13.4 marked the App Router stable. The `pages` directory with `getServerSideProps` and `getStaticProps` still works and is what migration questions compare against. - **Next.js 15** reversed the caching defaults: a bare `fetch` and `GET` route handlers are no longer cached unless you opt in, and request-bound APIs such as `params`, `searchParams`, `cookies()` and `headers()` became asynchronous. It also moved the App Router onto React 19. - **Next.js 16** made Turbopack the default bundler, which is why custom `webpack()` configuration questions now come with a migration angle. Explicit caching with `'use cache'` and Partial Prerendering developed across these releases behind configuration flags, so name the release and flag you mean when an answer depends on them. When an interviewer's mental model sounds like "fetch is cached by default", they are describing Next.js 13 or 14; saying so is part of a good answer.
Next.js is made by Vercel and built on React, and interviewers expect you to separate the two: Server Components and Suspense are React features, while file-system routing, the cache layers, middleware and the build pipeline are Next.js. Knowing which owns a behaviour tells you where to look when it misbehaves. It competes with other React meta-frameworks such as Remix, now continued as React Router's framework mode, which lean on web-standard loaders and actions over layered framework caching, and with Astro, which ships little or no JavaScript by default and suits content-heavy sites. Against a plain single-page app built with Vite, the trade is server infrastructure and framework rules in exchange for server rendering, smaller bundles and colocated data access. On the deployment side, Next.js runs on Vercel's managed platform, but also as a Node.js server, in a container, or as a static export when no server features are used. Some features depend on the host — image optimization, a shared cache across instances, edge execution — so a self-hosting answer should name what you now operate yourself. The [Deployment Targets](/topics/fe-nextjs-optimization-deployment-targets) section covers those choices.
explore
- Routing and Layouts30 questions
- App Router File Conventions5 questions
- Dynamic Segments and Catch-Alls5 questions
- Layouts, Templates, and Nesting4 questions
- Client Navigation APIs6 questions
- Pages Router vs App Router5 questions
- Rendering Modes18 questions
- Choosing SSR, SSG, or ISR5 questions
- Static vs Dynamic Rendering Triggers5 questions
- Streaming and loading.js4 questions
- Partial Prerendering4 questions
- Server Components20 questions
- The 'use client' Boundary4 questions
- Data Access in Server Components4 questions
- Serialization Across the Boundary3 questions
- Composition Across the Boundary5 questions
- Client Bundle Impact4 questions
- Server Actions23 questions
- 'use server' Semantics4 questions
- Invoking from Forms and Handlers4 questions
- Revalidating After Mutations5 questions
- Progressive Enhancement5 questions
- Security Posture of Actions5 questions
- Data Fetching and Caching27 questions
- Extended fetch Caching6 questions
- The Cache Layers5 questions
- Revalidation Strategies5 questions
- Opting Out of Caching5 questions
- 'use cache' and Explicit Caching6 questions
- Middleware and API Routes26 questions
- Matcher Configuration5 questions
- Rewrites, Redirects, and Headers5 questions
- Auth Gating Patterns4 questions
- Edge Runtime Constraints4 questions
- Route Handlers4 questions
- Middleware vs Route Handler vs Server Action4 questions
- Optimization and Deployment26 questions
- next/image6 questions
- next/font5 questions
- Dynamic Imports and Bundle Analysis5 questions
- Deployment Targets5 questions
- Turbopack5 questions
questions
170 · 7 sectionsIn a Next.js App Router project you create app/blog/[slug]/page.tsx. Which URLs does that one file serve, and how does the page component read the slug value?
basics
~20 sapp/blog/[slug]/page.tsx serves every single-segment URL under /blog, such as /blog/hello and /blog/42. Next passes the matched text to the page in the params prop as { slug: 'hello' }; since Next 15 params is a Promise, so await it.
In a Next.js App Router project you create the folder app/dashboard/settings/ and put a Settings.tsx component inside it, but visiting /dashboard/settings returns a 404. Why, and what actually makes a folder under app/ a routable URL?
basics
~20 sIn the Next.js App Router, folders only define URL segments. A segment becomes reachable only when it contains a page file that default-exports a component (or a route file for an API endpoint). Every other file in the folder is just colocated code.
In the Next.js App Router, what does a folder wrapped in parentheses — for example app/(marketing)/about/page.tsx — do to the resulting URL, and why would you create one?
basics
~20 sA parenthesised folder is a route group: Next omits it from the URL, so app/(marketing)/about/page.tsx still serves /about. Groups let you organise route files and scope a layout to a subset of routes without adding a URL segment.
In the Next.js App Router, what is special about the root layout at app/layout.tsx compared with a nested layout further down the tree?
basics
~20 sThe root layout is required, wraps every route in the app, and is the only layout that renders the <html> and <body> tags. Nested layouts render plain markup inside it and apply only to their own segment and below.
In a Next.js App Router app, what is the difference between a route that is prerendered at build time and one that is rendered on every request, in terms of when its data is read and what each visitor receives?
basics
~20 sA prerendered route fetches its data once during the production build and serves the same stored HTML to every visitor. A per-request route re-runs that code on each visit, so each visitor gets markup built from data read at that moment.
In the Next.js App Router, a page with no special configuration is prerendered at build time. Which APIs, when a Server Component in that route calls them, switch the whole route to rendering on every request instead?
basics
~10 sCalling a Dynamic API — cookies(), headers(), draftMode() from next/headers, connection() from next/server, or reading a page's searchParams prop — opts the entire route out of prerendering, so Next.js renders it per request.
In a Next.js App Router route segment, what does adding a loading.tsx file cause the framework to do, and which part of the UI does its output replace while data loads?
basics
~20 sNext.js wraps that segment's page.tsx and everything below it in a Suspense boundary whose fallback is loading.tsx's default export. The layout above stays on screen, and the fallback also appears instantly on client navigation into the route.
A Next.js App Router app has three pages: a marketing landing page, a news index that must be at most a minute out of date, and a signed-in account dashboard. Which rendering mode would you choose for each, and what drives each decision?
basics
~20 sPrerender the landing page at build time, give the news index a short revalidation window so it regenerates roughly every minute, and render the dashboard per request because its output depends on who is asking. The driver is whether output varies per request, then how stale it may be.
A Next.js App Router app adds a shared header in app/layout.tsx that awaits cookies() to greet the signed-in user. After that change, every route in the build output is listed as Dynamic, including the marketing pages. Explain why one call in the layout affects unrelated pages, and how you would get those pages prerendered again.
basics
~20 sNext.js decides static versus dynamic per route, and a route is the composition of the root layout plus every nested layout and the page. The root layout is part of every route, so its cookies() call opts them all out of prerendering.
In a Next.js App Router app, a Server Component page imports a 60 kB markdown-to-HTML library and renders the result. How much of that library's JavaScript reaches the browser bundle, and what does the browser get instead?
basics
~20 sNone of it. A library imported only by a Server Component runs at render time on the server, so the browser downloads zero bytes of it — only the rendered output, as HTML on the first load and as an RSC payload on client navigation.
In the Next.js App Router, `app/orders/page.tsx` queries the database directly and awaits the result. Which pieces of the classic browser-fetch setup does that remove, and what does the browser receive instead?
basics
~20 sapp/orders/page.tsx runs only on the server, so it awaits the query and renders the rows itself. The API route, the browser fetch, and the useEffect loading and error state all disappear. The browser receives rendered markup plus the RSC payload, never the query.
In the Next.js App Router, files under app/ render on the server unless told otherwise. Which of your components actually need a 'use client' directive, and which do not?
basics
~20 sOnly components that need browser behaviour: React state or effect hooks, DOM event handler props such as onClick, or browser APIs like window and localStorage. Everything else — markup, layout, data fetching — stays a Server Component with no directive.
In a Next.js App Router app you add a client-side ThemeProvider by wrapping {children} with it inside app/layout.tsx. Does that turn every page and component below it into client code? Explain what actually happens.
basics
~20 sNo. Only the provider module and its own imports become client code. The pages arrive as the layout's children prop — created by the Server Component layout, rendered on the server, and handed to the provider as an already-rendered slot.
In a Next.js App Router page, a Server Component loads a user row with 30 columns, renders the name as text, and passes only { id, name } into a Client Component. Which of that data actually reaches the browser, and how would you verify it?
basics
~20 sTwo things reach the browser: the markup the Server Component rendered, and a verbatim copy of the props handed to the Client Component. The other 28 columns stay on the server. Verify by searching the page source for a value you never passed.
In a Next.js App Router app, one form is written as <form action={createTodo}> where createTodo is a Server Action, and another as <form onSubmit={handleSubmit}> whose handler calls the same Server Action. Which one still submits if the page's JavaScript never loads, and why?
basics
~20 sOnly the form using the action prop still submits. Next renders it as an ordinary POST form carrying the action's identity in hidden fields, so the browser can submit it natively. An onSubmit handler cannot run until JavaScript loads and hydrates the page.
Inside a Next.js Server Action declared as async function createUser(formData: FormData), what does formData.get('email') actually return, and why can that value not be passed straight into your database call?
basics
~20 sformData.get('email') returns FormDataEntryValue | null — a string, a File, or null if the field was absent. The FormData type annotation is erased at runtime and the body is whatever the caller posted, so the action must parse and validate before using the value.
In the Next.js App Router, what does the 'use server' directive actually do to a function, and why is it wrong to think of it as the mirror image of 'use client'?
basics
~20 s'use server' marks a function as a server function that client code may call over the network — Next turns it into an RPC entry point. It does not make anything a Server Component; App Router components already run on the server by default.
In a Next.js App Router app a hydrated page renders <form action={saveNote}> where saveNote is a Server Action. The user submits, the URL never changes, no fetch or setState appears anywhere in the code, and yet the page shows updated content. Walk through what actually happens between the click and the update.
basics
~20 sReact intercepts the submit, packs the named form controls into FormData, and POSTs it to the current URL, naming the action to run. Next executes the function on the server and returns an RSC payload that the router merges into the live page.
In a Next.js App Router app, a Server Action can finish a write by calling either revalidatePath or revalidateTag from 'next/cache'. What does each one key on, how does data get associated with a tag, and how do you decide which to call?
basics
~20 srevalidatePath keys on a route path and invalidates what that route cached; revalidateTag keys on a label you attached to the reads themselves, for example fetch(url, { next: { tags: ['posts'] } }). Use paths when you know the affected route, tags when the same data appears on many routes.
In a Next.js App Router page.tsx, what does `export const dynamic = 'force-dynamic'` do, and when would you add it?
basics
~20 sIt is a Route Segment Config export that forces the route to be rendered on the server for every request instead of being prerendered, so its HTML is never served out of Next's Full Route Cache.
A Next.js App Router page exports `export const revalidate = 3600`. Does Next.js rebuild that page once an hour on a schedule? Explain what actually triggers the rebuild.
basics
~20 sNo scheduler is involved. The number is a staleness window in seconds: after 3600 seconds the cached page is merely marked stale, and only the next incoming request for that route causes Next.js to regenerate it.
In the Next.js App Router, what does passing `{ cache: 'force-cache' }` to `fetch` inside a Server Component do, and is that already what a plain `fetch` with no options does?
basics
~20 sPassing cache: 'force-cache' stores that fetch's response in Next's server-side Data Cache so later requests reuse it instead of calling the origin. In Next 15 and 16 that is not the default: a bare fetch is uncached.
A Next.js App Router Server Component calls `fetch(url, { next: { revalidate: 60 } })`. What exactly does that 60 apply to?
basics
~20 sThe 60 seconds belongs to that one Data Cache entry — the one keyed from that URL and those options — not to the component, the page, or any other fetch. Supplying it also opts the fetch into caching.
The Next.js App Router is usually described as having four caching layers. Name them, and for each say where it physically lives and how long an entry lasts.
basics
~20 sFour layers: Request Memoization (one render pass, server memory), the Data Cache (persistent server store of fetch results), the Full Route Cache (prerendered route output on the server), and the Router Cache (visited segments in browser memory for the session).
In a Next.js App Router project, where must the middleware file live, and what does exporting `export const config = { matcher: [...] }` from it change about when the middleware function runs?
basics
~20 sNext.js reads a single middleware file at the project root, next to app/ (or inside src/). Exporting config.matcher restricts which request paths invoke it; with no matcher, the middleware function runs for every request the app serves.
In Next.js middleware, what is the difference between returning NextResponse.rewrite(url) and NextResponse.redirect(url)?
basics
~20 sNextResponse.rewrite serves a different route internally: the browser keeps the original URL and makes one request. NextResponse.redirect returns a 3xx with a Location header, so the browser makes a second request and the address bar changes.
In the Next.js App Router, how do you define an HTTP endpoint in a route.ts file, and what happens when a request arrives with a method the file does not export?
basics
~20 sA route.ts file turns its folder's path into an HTTP endpoint. You export one async function per HTTP method, named exactly GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS, and Next.js answers 405 Method Not Allowed for any method you did not export.
A Next.js app gates its routes in middleware by checking that a session cookie is present on the incoming request and redirecting to /login when it is missing. What does that check actually establish about the caller, and what does it leave unproven?
basics
~20 sIt proves only that the request carried a cookie with that name — any client can send one. It does not show the session is valid, unexpired, unrevoked, or entitled to the data, so verification has to happen where the data is read.
A Next.js App Router app can run server code in middleware.ts, in a route handler at app/api/.../route.ts, and in a Server Action marked with 'use server'. What decides which of the three a given piece of server logic belongs in?
basics
~20 sWho calls the code decides. Middleware handles cross-cutting work on every matched request before routing; a route handler is a public HTTP endpoint for callers outside your app; a Server Action is an internal mutation invoked by your own UI.
In a Next.js App Router app, do you have to configure anything for one route's JavaScript to stay out of another route's initial download, and what is next/dynamic for then?
basics
~10 sNothing to configure: Next.js code-splits per route automatically, so visiting /dashboard does not download /settings' client code. next/dynamic splits inside a route, deferring a heavy component until it is actually rendered or needed.
In a Next.js app, what does importing a font from `next/font/google` do that a `<link>` to fonts.googleapis.com does not — where does the browser actually fetch the font file from at runtime?
basics
~20 snext/font/google downloads the font files at build time and serves them from your own origin, so the browser never contacts Google. The build generates the @font-face CSS, and the extra DNS, TLS and stylesheet round trips disappear.
In a Next.js App Router app, what does the `<Image>` component from `next/image` do that a plain `<img>` tag does not, and why does it refuse to render without width and height (or `fill`)?
basics
~20 snext/image generates a responsive srcset, negotiates a modern format such as WebP or AVIF, lazy-loads by default, and requires intrinsic dimensions so the browser can reserve layout space before the bytes arrive, which prevents layout shift.
In a Next.js App Router app, what does the `ssr: false` option on `next/dynamic` change about where a component renders, and why does the build reject that option inside a Server Component?
basics
~20 sWith ssr: false, Next.js skips the component during server rendering and mounts it only in the browser after hydration, rendering the loading fallback in its place meanwhile. The App Router rejects the option in a Server Component because opting out of server rendering is a client-side decision.
In a Next.js app you set `output: 'standalone'` in next.config and build a Docker image from the result. What does that build produce, and what do you have to copy into the runtime image yourself?
basics
~20 sIt emits a self-contained .next/standalone folder with a server.js and only the traced node_modules the server needs, so the image runs node server.js without the full project. It does not include public or .next/static — copy those in yourself.