Interview Q&A · 101 questions · 21 answered publicly
Next.js Developer Interview Questions
Ordered by how often they're asked. Sign in free to see every answer, rate your confidence and run timed mock interviews.
-
Most asked What is Next.js and what problems does it solve on top of React?
Summary
Next.js is a React framework that adds file-based routing, server rendering (SSR, static generation, streaming), React Server Components, data fetching and caching, API endpoints (Route Handlers), image/font optimization and a production build pipeline.
Longer Answer
Plain React (e.g., a Vite SPA) renders in the browser and leaves routing, SEO, data loading and code splitting to you. Next.js renders on the server by default, sending HTML for fast first paint and SEO, then hydrates interactive parts. With the App Router, components are Server Components unless marked
'use client', which reduces the JavaScript shipped to the browser.Key Points
- File-system routing (App Router and Pages Router)
- SSR, SSG, ISR and streaming
- React Server Components by default
- Route Handlers for backend endpoints
- Built-in image, font and script optimization
-
Most asked What are the differences between the App Router and the Pages Router?
Summary
The App Router (
app/directory, stable since Next.js 13.4) is built on React Server Components with nested layouts, streaming, Server Actions and colocated loading/error UI. The Pages Router (pages/) usesgetServerSideProps/getStaticPropsand client-rendered page components.Longer Answer
Both can coexist during migration. App Router concepts:
layout.tsx(persistent shared UI),page.tsx(route UI),loading.tsx(Suspense fallback),error.tsx(error boundary),route.ts(API handlers), and async Server Components that fetch data directly. Navigation hooks come fromnext/navigationinstead ofnext/router. New projects should use the App Router.Key Points
- App Router: RSC, nested layouts, streaming, Server Actions
- Pages Router: getServerSideProps/getStaticProps
- Can coexist for incremental migration
- Different router hooks (
next/navigationvsnext/router)
Comparison / Tradeoffs
Concept Pages Router App Router Data fetching getServerSideProps / getStaticProps async Server Components, fetch, caching APIs Layouts _app.tsx, manual Nested layout.tsxAPI pages/api/* route.ts Route Handlers Mutations API routes Server Actions -
Most asked What is the difference between Server Components and Client Components?
Summary
Server Components render only on the server: they can be async, access databases and secrets directly, and send no JavaScript for themselves to the browser. Client Components (marked with
'use client') render on the server for the initial HTML and then hydrate in the browser, so they can use state, effects, event handlers and browser APIs.Longer Answer
In the App Router, everything is a Server Component by default.
'use client'marks a boundary: that module and everything it imports become part of the client bundle. Server Components can render Client Components and pass them serializable props (or other Server Components aschildren). Client Components can't import Server Components directly, but can receive them as props.Code Example
// app/products/page.tsx (Server Component) import { AddToCart } from "./add-to-cart"; export default async function ProductsPage() { const products = await db.product.findMany(); // runs on the server only return ( <ul> {products.map((p) => ( <li key={p.id}> {p.name} <AddToCart productId={p.id} /> </li> ))} </ul> ); } // app/products/add-to-cart.tsx "use client"; import { useState } from "react"; export function AddToCart({ productId }: { productId: string }) { const [added, setAdded] = useState(false); return <button onClick={() => setAdded(true)}>{added ? "Added" : "Add to cart"}</button>; }Key Points
- Server by default in
app/ 'use client'marks a client boundary- Server: async, direct data access, zero JS
- Client: hooks, events, browser APIs
- Props crossing the boundary must be serializable
- Server by default in
-
Most asked Explain the App Router file conventions: page, layout, loading, error, not-found, template and route.
Summary
page.tsxdefines a route's UI;layout.tsxwraps child segments and persists across navigation;loading.tsxis an automatic Suspense fallback;error.tsxis an error boundary (must be a Client Component);not-found.tsxrenders fornotFound();template.tsxis like a layout but remounts on navigation;route.tsdefines HTTP handlers.Longer Answer
Folders define URL segments, and only folders with
page.tsxorroute.tsare publicly routable, so you can colocate components.global-error.tsxcatches errors in the root layout. Layouts don't re-render on navigation between child pages, which preserves state.Key Points
- Folders = segments;
page/routemake them routable - Layouts persist, templates remount
loading.tsx→ Suspenseerror.tsxmust be'use client'
- Folders = segments;
-
Most asked How does data fetching work in the App Router?
Summary
Server Components can be
asyncand fetch data directly withfetchor any database/ORM client. Next.js adds caching and revalidation options on top:fetch(url, { next: { revalidate: 60, tags: ['posts'] } }), segment-levelexport const revalidate, and (in newer versions) the'use cache'directive.Longer Answer
Fetch data where it's needed: identical
fetchcalls during one render are deduplicated (request memoization), and you can wrap non-fetch data functions in React'scache()for the same effect. Avoid waterfalls by starting independent requests in parallel (Promise.all) and streaming slower parts behind<Suspense>. Client-side fetching (SWR, TanStack Query) is still useful for highly interactive or user-specific live data.Code Example
export default async function Dashboard() { const [user, stats] = await Promise.all([ getUser(), // React cache()-wrapped DB call fetch("https://api.example.com/stats", { next: { revalidate: 60, tags: ["stats"] } }).then((r) => r.json()), ]); return <Overview user={user} stats={stats} />; }Key Points
- Async Server Components fetch directly
- Request memoization dedupes identical fetches
revalidateand tags control freshness- Parallelize with
Promise.all; stream with Suspense
-
Most asked How did caching defaults change in Next.js 15?
Summary
Next.js 15 made caching opt-in:
fetchrequests are no longer cached by default, GET Route Handlers are not cached by default, and the client Router Cache no longer reuses page segments (stale time 0) on navigation.Longer Answer
In Next.js 14,
fetchdefaulted toforce-cache, which surprised many developers with stale data. In 15 you explicitly opt in withcache: 'force-cache',next: { revalidate }, or segment config likeexport const dynamic = 'force-static'. Pages without dynamic APIs can still be statically pre-rendered at build time. Next.js 15 also made request APIs (cookies(),headers(),params,searchParams) asynchronous.Key Points
fetchuncached by default in 15- GET Route Handlers uncached by default
- Router Cache staleTime 0 for pages
- Async
cookies(),headers(),params
-
Most asked Explain SSR, SSG, ISR and CSR in Next.js.
Summary
SSG pre-renders pages at build time; ISR (Incremental Static Regeneration) re-generates static pages in the background after a revalidation period or on demand; SSR renders on every request; CSR renders in the browser after loading JavaScript.
Longer Answer
App Router mapping: a route is static by default if it uses no dynamic APIs (SSG).
export const revalidate = 60orfetch(..., { next: { revalidate: 60 } })gives ISR. Usingcookies()/headers()/uncached data makes it dynamic (SSR). Client Components with client-side fetching are CSR. Choose based on data freshness and personalization needs.Key Points
- SSG: build time, fastest
- ISR: static + periodic/on-demand refresh
- SSR: per request, personalized
- CSR: browser rendering for interactivity
Comparison / Tradeoffs
Strategy When rendered Best for SSG Build Docs, marketing ISR Build + revalidate Catalogs, blogs SSR Each request Personalized dashboards CSR Browser Highly interactive widgets -
Most asked What are Server Actions and how do you use them for mutations?
Summary
Server Actions are async functions marked with
'use server'that run on the server and can be called from forms (<form action={createPost}>) or Client Components. Next.js handles the network request, and the action can revalidate caches and redirect.Longer Answer
They remove the need for separate API routes for many mutations and work with progressive enhancement (forms submit before JS loads). Use
useActionState(React 19) for pending state and returned errors, anduseFormStatusfor submit button state. Security: every Server Action is a public HTTP endpoint, so always validate input (e.g., with Zod) and check authentication/authorization inside the action.Code Example
// app/posts/actions.ts "use server"; import { z } from "zod"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; const PostSchema = z.object({ title: z.string().min(3), body: z.string().min(10) }); export async function createPost(prevState: unknown, formData: FormData) { const session = await auth(); if (!session) return { error: "Not signed in" }; const parsed = PostSchema.safeParse(Object.fromEntries(formData)); if (!parsed.success) return { error: parsed.error.flatten().fieldErrors }; const post = await db.post.create({ data: { ...parsed.data, authorId: session.user.id } }); revalidatePath("/posts"); redirect(`/posts/${post.id}`); }Key Points
'use server'functions callable from forms/clients- Revalidate with
revalidatePath/revalidateTag useActionState/useFormStatusfor UX- Treat as public endpoints: validate and authorize
-
Most asked What happens, step by step, when a request reaches a Next.js App Router application?
Summary
next.config headers, redirects and rewrites apply; the proxy (middleware.ts before Next.js 16) runs for matched paths and may redirect, rewrite or respond; routing serves static assets directly or matches an app route; server components render on the server (fetching data, using caches where configured) to HTML for the first load or an RSC payload for client navigations; route handlers and server actions handle API requests and mutations; in the browser, client components hydrate and links prefetch routes.
Longer Answer
Consequences: a proxy without a matcher runs for every asset and prefetch, so keep it cheap and authorise near the data (server components, route handlers, server actions). Layouts persist across client navigations, so they don't re-run for every page change.
Key Points
- Config redirects/rewrites → proxy → routing.
- Server components render on the server.
- Route handlers and server actions for APIs and mutations.
- Client components hydrate; links prefetch.
Deep dive: Request Lifecycle course: Next.js: Proxy (Middleware), Rendering and Caching
-
Most asked How do dynamic routes, catch-all and optional catch-all segments work?
Summary
[slug]matches one segment,[...slug]matches one or more segments (array), and[[...slug]]also matches the parent path with no segments. Params arrive in the page'sparamsprop.Longer Answer
In Next.js 15+,
paramsandsearchParamsare Promises in Server Components, so youawait params. UsegenerateStaticParamsto pre-render known params at build time.Code Example
// app/blog/[slug]/page.tsx export default async function Post({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const post = await getPost(slug); if (!post) notFound(); return <article>{post.title}</article>; } export async function generateStaticParams() { const posts = await getAllPosts(); return posts.map((p) => ({ slug: p.slug })); }Key Points
[id]single segment[...parts]one or more[[...parts]]zero or moreparamsis a Promise in Next 15+
-
Most asked How does streaming with Suspense work in Next.js?
Summary
The server sends HTML in chunks: the shell (layout plus fast parts) is sent immediately, and slower components wrapped in
<Suspense fallback={...}>stream in when their data resolves, without blocking the whole page.Longer Answer
loading.tsxautomatically wraps a page in Suspense. Place Suspense boundaries around slow, independent sections (recommendations, comments) to improve Time To First Byte and First Contentful Paint. Streaming works with SSR; SEO still gets the full HTML, since crawlers receive the completed stream.Code Example
import { Suspense } from "react"; export default function ProductPage({ params }: { params: Promise<{ id: string }> }) { return ( <> <ProductDetails params={params} /> <Suspense fallback={<p>Loading reviews…</p>}> <Reviews params={params} /> {/* slow async server component */} </Suspense> </> ); }Key Points
- Shell first, slow parts stream later
loading.tsx= route-level Suspense- Granular
<Suspense>boundaries - Improves TTFB/FCP
-
Most asked What are Route Handlers and when should you use them instead of Server Actions?
Summary
Route Handlers (
app/api/.../route.ts) export functions named after HTTP methods (GET,POST, ...) using WebRequest/ResponseAPIs. Use them for public REST endpoints, webhooks, third-party callbacks, file downloads and mobile clients; use Server Actions for mutations triggered from your own UI.Longer Answer
Route Handlers support streaming responses,
NextResponse.json(), cookies and headers, and can run on Node or Edge runtimes. In Next.js 15+, GET handlers aren't cached by default (export const dynamic = 'force-static'opts in).Code Example
// app/api/webhooks/stripe/route.ts import { NextResponse } from "next/server"; export async function POST(req: Request) { const body = await req.text(); const sig = req.headers.get("stripe-signature")!; const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!); await handleEvent(event); return NextResponse.json({ received: true }); }Key Points
- Export
GET,POST, etc. fromroute.ts - Web Request/Response APIs
- Webhooks, public APIs, mobile clients
- Server Actions for UI mutations
- Export
-
Most asked What is Next.js middleware (renamed `proxy` in Next.js 16) and what should it be used for?
Summary
Middleware (
middleware.ts, calledproxy.tsfrom Next.js 16) runs before a request is matched to a route, so it can rewrite, redirect, set headers/cookies or return early. It's good for lightweight concerns like locale redirects, A/B rewrites, and coarse auth redirects.Longer Answer
It runs for every matched request, so keep it fast and limit it with
config.matcher. Don't rely on it as the only authorization layer: check auth again in Server Components, Server Actions and Route Handlers close to the data. A 2025 vulnerability (CVE-2025-29927) let attackers bypass middleware via a crafted internal header, which shows why defense in depth matters.Code Example
// middleware.ts (proxy.ts in Next.js 16) import { NextResponse, type NextRequest } from "next/server"; export function middleware(req: NextRequest) { const hasSession = req.cookies.has("session"); if (!hasSession && req.nextUrl.pathname.startsWith("/dashboard")) { return NextResponse.redirect(new URL("/login", req.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard/:path*"] };Key Points
- Runs before routing; rewrite/redirect/headers
- Use
matcherto scope it - Keep it fast and light
- Not the only auth check (defense in depth)
Deep dive: Request Lifecycle course: Next.js: Proxy (Middleware), Rendering and Caching
-
Most asked How do `revalidatePath` and `revalidateTag` work?
Summary
revalidatePath('/posts')invalidates cached data and rendered output for a path;revalidateTag('posts')invalidates all cached fetches/entries taggedposts. Both are called from Server Actions or Route Handlers after mutations or webhooks.Longer Answer
Tag-based invalidation is more precise: tag the fetch (
next: { tags: ['post:42'] }) and invalidate exactly what changed. On-demand revalidation via a webhook (e.g., from a CMS) keeps static pages fresh without short time-based intervals. Recent versions also addupdateTagfor read-your-own-writes semantics within Server Actions.Key Points
- Path-based vs tag-based invalidation
- Call after mutations or CMS webhooks
- Tag fetches precisely
- Combine with time-based
revalidate
-
Most asked How do you manage metadata and SEO in the App Router?
Summary
Export a static
metadataobject or an asyncgenerateMetadata()from layouts and pages; Next.js merges them down the tree and renders<title>, meta descriptions, Open Graph and Twitter tags. Usesitemap.ts,robots.tsandopengraph-image.tsxfile conventions for the rest.Longer Answer
generateMetadatacan fetch data (deduplicated with the page's fetch). Usetitle.templatein the root layout ('%s | Acme'). Server rendering means crawlers receive full HTML. Add JSON-LD structured data via a<script type='application/ld+json'>in the page.Code Example
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) { const post = await getPost((await params).slug); return { title: post.title, description: post.excerpt, openGraph: { images: [post.coverUrl] }, }; }Key Points
metadata/generateMetadata- Merged from layouts to pages
sitemap.ts,robots.ts, OG image routes- Title templates
-
Most asked What does `next/image` do?
Summary
<Image>automatically resizes, optimizes and serves modern formats (WebP/AVIF), lazy-loads images by default, prevents layout shift by requiring dimensions (orfill), and generates responsivesrcsets.Longer Answer
Remote images need
images.remotePatternsconfigured. Usepriority(orfetchPriority='high') for the Largest Contentful Paint image,sizesfor responsive layouts, andplaceholder='blur'for nicer loading. Self-hosting needs the optimization server (or a custom loader / CDN).Key Points
- Automatic resizing and modern formats
- Lazy loading by default
- Width/height or
fillprevents CLS priorityfor the LCP imageremotePatternsfor external hosts
-
Most asked How do environment variables work in Next.js, and what is exposed to the browser?
Summary
Variables in
.env*files are available on the server viaprocess.env. Only variables prefixed withNEXT_PUBLIC_are inlined into the client bundle at build time, so never put secrets inNEXT_PUBLIC_variables.Longer Answer
NEXT_PUBLIC_values are baked in at build time, so changing them requires a rebuild (unless you read them at runtime on the server and pass them down). Use theserver-onlypackage to make modules containing secrets fail the build if imported into client code.Key Points
process.envon the serverNEXT_PUBLIC_*inlined in client bundle at build- Never expose secrets with that prefix
server-onlyguards secret modules
-
Most asked How do you implement authentication in a Next.js App Router app?
Summary
Use a library such as Auth.js (NextAuth v5), Clerk, Better Auth or a custom session system: store sessions in HttpOnly cookies, read the session in Server Components/Actions/Route Handlers via
cookies()or the library'sauth(), and protect routes with server-side checks (optionally with middleware redirects).Longer Answer
Centralize authorization in a data access layer (DAL) that verifies the session before returning data, so every page and action goes through it. Don't rely only on hiding UI or on middleware. Use secure,
SameSitecookies, and for credentials auth hash passwords properly.Key Points
- Session in HttpOnly cookies
- Check auth in server code near data access
- Data Access Layer pattern
- Middleware only for coarse redirects
-
Most asked What causes hydration mismatch errors and how do you fix them?
Summary
Hydration errors occur when the HTML rendered on the server differs from what React renders on the client's first pass, e.g. from using
Date.now(),Math.random(),window/localStorage, locale-dependent formatting, or invalid HTML nesting.Longer Answer
Fixes: render browser-only values in
useEffectafter mount, usedynamic(() => import(...), { ssr: false })from a Client Component for browser-only components, pass deterministic data from the server, fix invalid nesting (e.g.,<div>inside<p>), and usesuppressHydrationWarningonly for unavoidable cases like timestamps. Browser extensions modifying the DOM can also trigger them.Key Points
- Server and client output must match
- Defer browser-only values to effects
dynamic(..., { ssr: false })- Fix invalid HTML nesting
-
Most asked How do you optimize Core Web Vitals in a Next.js app?
Summary
Minimize client JavaScript (keep components on the server, push
'use client'down the tree), optimize the LCP image withnext/imagepriority, usenext/font, stream slow content with Suspense, avoid layout shift with sized media, and defer third-party scripts withnext/scriptstrategies.Longer Answer
Analyze bundles with
@next/bundle-analyzer, lazy-load heavy client components withnext/dynamic, and avoid large client-side libraries for things the server can do. Measure with Lighthouse, Web Vitals reporting (useReportWebVitals) and real-user monitoring (INP, LCP, CLS).Key Points
- Less client JS via Server Components
- LCP image priority
- Stream slow sections
- Bundle analysis + dynamic imports
- Measure INP/LCP/CLS in the field
-
Most asked How do `getServerSideProps`, `getStaticProps` and `getStaticPaths` work in the Pages Router?
Summary
getServerSidePropsruns on every request and passes props to the page (SSR);getStaticPropsruns at build time (with optionalrevalidatefor ISR);getStaticPathslists dynamic paths to pre-render, withfallbackcontrolling unknown paths.Longer Answer
fallback: false404s unknown paths,trueserves a fallback UI then renders, and'blocking'renders on first request like SSR, then caches. These functions only run on the server, so they can access secrets. In the App Router, async Server Components replace them.Key Points
getServerSideProps: per requestgetStaticProps+revalidate: SSG/ISRgetStaticPaths+fallbackmodes- Replaced by async Server Components in App Router
- How can a Client Component render Server Component content?
- What are route groups, parallel routes and intercepting routes?
- Describe the caching layers in the Next.js App Router.
- How does navigation work with `<Link>` and `useRouter` in the App Router?
- What are `usePathname`, `useSearchParams` and `useParams`, and what's the Suspense caveat?
- How does error handling work in the App Router?
- What are the options for deploying a Next.js application?
- How do you build forms with Server Actions, validation and pending states?
- What is a Data Access Layer (DAL) and why is it recommended in Next.js?
- What security considerations apply specifically to Server Actions and Server Components?
- What is the RSC payload?
- Which props can be passed from a Server Component to a Client Component?
- What does `next/font` provide?
- What's the difference between the Node.js and Edge runtimes in Next.js?
- How do you load third-party scripts efficiently in Next.js?
- How does `next/dynamic` work and when do you use it?
- What is `useOptimistic` and how does it work with Server Actions?
- How do you design good loading states in the App Router?
- Why don't layouts re-render on navigation, and what are the implications?
- How do you implement internationalization in the App Router?
- How do you test a Next.js application?
- What is Turbopack?
- How do redirects, rewrites and headers work in `next.config`?
- How do you add a Content Security Policy to a Next.js app?
- What is Partial Prerendering (PPR) / Cache Components?
- What does the `'use cache'` directive do?
- What's the difference between React's `cache()` and Next.js's `unstable_cache`?
- What is the `after()` API in Next.js 15?
- How do you add observability to a Next.js app?
- How do you access a database from Next.js safely and efficiently?
- How does state management change with Server Components?
- What styling options work with the App Router and Server Components?
- How do API Routes in the Pages Router differ from Route Handlers?
- How would you migrate a large Next.js app from the Pages Router to the App Router?
- How does React 19's `use()` hook help with data in Next.js?
- How are static assets served in Next.js?
- What does `generateStaticParams` do and what is `dynamicParams`?
- What are route segment config options?
- How do you read and set cookies and headers in the App Router?
- How do `redirect()`, `permanentRedirect()` and `notFound()` work?
- Why does `next/image` require `remotePatterns` for external images?
- When does `<Link>` prefetch, and how can you control it?
- How do you avoid request waterfalls in Server Components?
- How do you add real-time features to a Next.js app?
- When would you use a custom Node server with Next.js, and what do you lose?
- How do you structure a Next.js app in a monorepo?
- How does Next.js support TypeScript?
- What does Next.js do for accessibility, and what remains your job?
- How should errors in Server Actions be handled for good UX?
- What is `output: 'export'` and what are its limitations?
- How do you find and reduce large client bundles in Next.js?
- What is the `next/form` component?
- How would you build a multi-tenant SaaS on Next.js with custom domains or subdomains?
- What do the `server-only` and `client-only` packages do?
- What breaking changes should you expect when upgrading to Next.js 15?
- What are notable changes in Next.js 16?
- How does Next.js compare with Remix/React Router v7 and Astro?
- What is Draft Mode and how is it used with a headless CMS?
- How do you generate dynamic Open Graph images in Next.js?
- What is required in the root layout of an App Router app?
- When would you use `template.tsx` instead of `layout.tsx`?
- How do you colocate non-route files inside the `app` directory?
- How do you read query parameters in a Server Component page?
- How would you implement pagination and filters in the App Router?
- How do you implement a URL-addressable modal in the App Router?
- How do you make a Route Handler's GET response static or cached?
- How do you stream a response (e.g., AI tokens) from a Route Handler?
- Compare Auth.js, Clerk and rolling your own authentication in Next.js.
- How should you handle third-party webhooks in Next.js?
- How does image optimization work when self-hosting Next.js?
- How can you preload critical resources in the App Router?
- How do you call a Server Action from an event handler instead of a form?
- How do you rate limit Server Actions or Route Handlers in Next.js?
- What is the React Compiler and how does it relate to Next.js?
- How do you debug unexpected stale data in a Next.js App Router app?
- What do the symbols in `next build` output (○, ●, ƒ) mean?
- How do you handle runtime configuration that changes per environment without rebuilding?
- How does Next.js protect against XSS and where can you still introduce it?
- How do you investigate a production-only error that shows 'An error occurred in the Server Components render'?
- What should you consider for focus management during client-side navigation in Next.js?