92 Next.js interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
Next.js is a React framework that provides routing, server-side rendering and tooling for production applications. The questions cover the App Router versus the Pages Router, SSR and other rendering strategies, Server and Client Components, Route Handlers, Server Actions, image optimisation, migration, deployment, self-hosting with Docker, and static export.
and 37 more topics.
Key differences include: - Architecture: App Router (Next.js 13+) uses the app/ directory and supports React Server Components by default. Pages Router uses the pages/ directory: pages are still rendered to HTML on the server (SSR/SSG), but the JavaScript for every component is sent to…
In the App Router, the folder structure inside app/ is the URL. Each folder is a route segment, and a segment only becomes a reachable page when it has a page.tsx. Folder names decide how URLs match: - [slug]: a dynamic segment, its value read…
A layout is UI shared by several pages, declared in a layout.tsx file. It receives a children prop, which is the page (or child layout) inside it. When you navigate between pages that share a layout, the layout does not remount, so its state is…
loading.tsx is a special file in a route segment: Next.js automatically wraps that segment's content in a Suspense boundary and uses the component from loading.tsx as the fallback. So on navigation users see a skeleton right away instead of waiting for data. The commonly misunderstood…
error.tsx is an error boundary for a route segment: when the page or a child component throws during render, Next.js shows the UI from error.tsx in place of the broken part. not-found.tsx is the UI shown when code calls notFound() in that segment; the root…
A Route Group is a folder whose name is wrapped in parentheses, such as (auth). It groups routes so they can share a layout, but the group name does not appear in the URL. /login and /register both live in (auth), so they share (auth)/layout.tsx,…
A dynamic route is a folder named in square brackets, such as [slug]. The URL segment in that position is captured as a variable and passed to the page through the params prop. The App Router has three forms: Folder Matching URL params --------- app/blog/[slug]/…
In the App Router you declare metadata by exporting it from layout.tsx or page.tsx; Next.js generates the <head tags such as <title, description and Open Graph for you. export const metadata export async function generateMetadata() --------- Use when Values are fixed You need dynamic data:…
generateStaticParams is exported from a dynamic route page to pre-generate static paths at build time — the App Router equivalent of getStaticPaths. Combined with Static Generation it builds a static page for every possible parameter value. For a slug that is not in the list,…
React Server Components (RSC) are components that run only on the server: their code is not sent to the browser, which only receives the rendered result. In the Next.js App Router every component is a Server Component by default; a component that needs interactivity goes…
Put 'use client' on the first line of a file to make it a Client Component: its code is sent to the browser and runs there. By default every component in the App Router is a Server Component, so add this line only when the…
A Server Component can import and render a Client Component — this is the normal dependency direction. The reverse is not allowed: a Client Component CANNOT import a Server Component. The reason is that 'use client' marks a boundary: every file imported from a 'use…
Use a Server Component when you need: data fetching, access to backend resources, keeping sensitive data (API keys) off the client, or reducing the client bundle. Use a Client Component when you need: onClick/onChange event handlers, useState/useEffect, browser APIs, real-time updates, or custom hooks. Default…
No. Context (createContext, useContext, Provider) needs React running on the client, so it cannot be used in a Server Component: importing createContext into a Server Component makes Next.js fail the build right away. The way to do it: make the Provider a Client Component that…
In the App Router every component is a Server Component by default: it runs on the server, with no state, no event handlers and no window. Many npm packages were written before Server Components existed and use useState, useEffect, createContext or DOM APIs without a…
server-only and client-only are two packages that mark a module as usable on one side only. Add import 'server-only' at the top of a file and any Client Component importing it fails the build. client-only does the opposite, for code that uses window. Why you…
SSR (Server-Side Rendering) means rendering HTML on the server on every request and sending HTML that already has content to the browser. Users see the page right away instead of waiting for JavaScript to load before any text appears. In the App Router, a page…
SSG (Static Site Generation) renders a page to HTML at build time (next build) and serves that file for every request, usually from a CDN. The server does not render again for each visitor, so the page is returned very quickly. At build time Next.js…
ISR blends SSG and SSR: pages are statically generated but can be regenerated in the background after a revalidate interval. The first user after the interval receives stale content and triggers a background regeneration; subsequent users get the fresh version. - Pages Router: return {…
On-demand revalidation means telling Next.js that some data is stale at the moment it changes, instead of waiting for a revalidate: 60 timer to expire. The typical case: an editor updates a post in the CMS, the CMS calls a webhook on your app, and…
In the App Router, Next.js extends server-side fetch with options that store the response in the Data Cache, a server-side cache that persists across requests and deployments. Since Next.js 15, nothing is cached by default: you opt in per call. The three calls behave differently:…
- Static rendering: happens at build time, cached and served from a CDN. - Dynamic rendering: happens per request, not cached. A route becomes dynamic automatically when it uses: await cookies(), await headers(), searchParams, or fetch with cache: 'no-store'. Be explicit with export const dynamic…
getStaticProps runs at build time and embeds data into the static HTML, so it is served very fast as a ready-made file, which suits data that rarely changes. Returning revalidate too (e.g. return { props, revalidate: 60 }) enables ISR: after 60 seconds, the next…
Streaming SSR means the server sends HTML in several chunks: what is ready goes out immediately, and parts waiting on data follow later. Regular SSR has to wait for every query before sending the first byte, so one slow API slows down the whole page.…
Route Handlers are how you create API endpoints in the App Router by placing a route.ts file inside any directory under app/. Each HTTP method is exported as a named function. They use standard Web APIs (Request/Response) instead of Node.js req/res. In POST, the body…
Server Actions are async functions that run on the server and can be called from Client Components or HTML forms. Declare them with the 'use server' directive. They allow mutating data directly without building a separate API endpoint. Security note: every Server Action is effectively…
A Server Action is an async function marked with 'use server' that runs on the server but can be passed straight to a <form's action prop. On submit, React collects the inputs into a FormData, sends it to the server and calls that function. What…
After a Server Action writes to the database, any cache still holding the old data (the fetch Data Cache, 'use cache', prerendered pages) knows nothing about the change. You have to tell Next.js to invalidate the related cache so the next render picks up fresh…
A Server Action has two kinds of errors, handled differently. Expected errors (invalid input, email already taken, out of stock) are returned as an error object for the form to display. Unexpected errors (bugs, the database is down) are simply thrown, and the nearest error…
Since Next.js 16, Middleware has been renamed to Proxy: a proxy.ts file at the project root (or inside src/) that exports a proxy function. It runs before a route is rendered, receives the request and decides: let it continue, redirect, rewrite to another URL, modify…
cookies() and headers() are imported from next/headers and work in Server Components, Server Actions and Route Handlers. Since Next.js 15 both are async and must be awaited; Next.js 16 removed synchronous access entirely. Read and write rules: - Reading: cookieStore.get('theme') returns a { name, value…
An optimistic update shows the result in the UI as soon as the user acts, before the server confirms, so the interface does not sit waiting on the network. React 19's useOptimistic creates a temporary copy of state that only exists while an action is…
next/image automatically: - Generates multiple sizes plus a srcset so the browser picks one that fits the viewport/DPR (paired with the sizes prop). - Converts to a modern format: WebP by default; AVIF must be enabled via images.formats. - Lazy-loads by default. For the LCP…
next/font downloads fonts at build time and serves them as static files from your own app (self-hosting), and it also generates a fallback font sized to match the real one. The result: the browser never calls Google, and text does not jump when the font…
Prefetching is <Link loading the target route's data in the background as soon as the link enters the viewport, so the new page appears almost instantly when the user clicks. It only runs in production (next build + next start), so you will not see…
next/script is the <Script component for loading third-party scripts (analytics, chat widgets...) without slowing the page down. The key prop is strategy: it decides when the script loads relative to hydration, the moment React attaches event handlers to the server HTML. - beforeInteractive: injected into…
The proxy pattern lets the browser call your Next.js app's own domain while the app forwards (rewrites) the request to the real backend. The browser only sees the app's URL and never learns the backend address. Since Next.js 16, middleware.ts is renamed to proxy.ts (the…
Core Web Vitals are the three metrics Google uses to measure real user experience, evaluated at the 75th percentile (75% of visits must meet the threshold): Metric What it measures "Good" threshold --------- LCP (Largest Contentful Paint) When the largest element in the initial viewport…
Next.js loads .env files into process.env automatically. The key rule: variables without a prefix exist only on the server; variables prefixed with NEXTPUBLIC have their value copied into the JS bundle during next build so the client can read them. At build time, Next.js finds…
Vercel is built by the makers of Next.js, so it's the most optimized target: push to Git → Vercel builds and deploys automatically. Vercel does for you: - Server Components / SSR / Route Handlers run on Vercel Functions (Node.js runtime) — auto-scaling per request.…
Default approach: next build then next start runs a Node server serving both static assets and SSR/Route Handlers. You put it behind a reverse proxy (Nginx) and need the .next folder plus all of nodemodules. Problem: copying the entire nodemodules (hundreds of MB) into an…
Goal: small image, good build cache, no devDependencies in runtime. The standard is a multi-stage build combined with output: 'standalone'. Why multi-stage: the final stage takes only standalone (dependency-traced, keeping only files that are actually imported) → no source code, devDeps or full nodemodules. What…
output: 'export' builds the app into pure static HTML/CSS/JS in an out/ folder, deployable to any static host (S3, GitHub Pages, Nginx) — no Node server needed. Picture it: like exporting a website to files and dropping them on a drive — no server runs…
CSS Modules and Tailwind process styles at build time (compiling to a static CSS file) → they work naturally with Server Components, no client JS runtime needed. This is the recommended approach for App Router. Runtime CSS-in-JS (styled-components, Emotion) generates CSS at render time using…
Next.js ships a next/jest helper that handles the config (SWC transform, CSS/image/next/font mocks, .env loading). Install jest, jest-environment-jsdom, @testing-library/react, @testing-library/dom and @testing-library/jest-dom, then create the config file: jest.setup.js needs a single line, import '@testing-library/jest-dom', to get matchers such as toBeInTheDocument(). This setup is for unit…
Playwright runs the app in a real browser (Chromium/Firefox/WebKit), so it tests exactly what users see — including Server Components, streaming, and Server Actions that unit tests can't reach. Picture it: Playwright is a bot that opens a browser, clicks, and reads the DOM like…
In the Pages Router these are two special files: - app.tsx — wraps every page; the place for shared layout, global CSS, providers (theme, store) and persisting state across navigations. Runs on both server and client. - document.tsx — customizes the outermost HTML structure (<html,…
Both mark the cache as stale after data changes (usually called in a Server Action or Route Handler). They differ in what they target. revalidatePath(path) — targets a route path. Use it when you know exactly which page is affected and it is concentrated in…
App Router has no built-in i18n config like Pages Router did; you build routing with a dynamic [locale] segment + proxy.ts to detect/redirect the language (since Next.js 16, middleware.ts is renamed to proxy.ts). proxy.ts reads Accept-Language or a cookie and redirects / → /vi. generateStaticParams…
The two hooks complement each other when building forms with Server Actions: useActionState (React, in a Client Component) — wraps an action and keeps its returned state (validation errors, results) across submits. It returns three values: state, a formAction to attach to the form, and…
Draft Mode lets editors preview unpublished CMS drafts on pages that are normally statically rendered (SSG/ISR) — i.e. bypass the cache and fetch unpublished content. Mechanism: a Route Handler calls (await draftMode()).enable(), and Next.js sets a signed cookie; while the cookie is present, pages switch…
'use client' is not a label on one file — it marks the boundary between two module graphs. Everything imported from that file downward is treated as client code and ships in the browser bundle. Putting it in the root layout turns that layout and…
You get an error like Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Reason: props crossing the server → client boundary must be serializable so they can be embedded in the RSC payload. React…
Both wrap child routes; they differ in lifecycle across navigation: - layout.tsx: keeps the same instance when moving between child routes. State survives, effects do not re-run, the DOM is not remounted. - template.tsx: creates a new instance on every navigation. State resets, useEffect runs…
No — within a single server render only one request actually goes out. This is request memoization: React caches fetch results by (URL + options) for the lifetime of one request, and later calls reuse the existing result. That is why you do not need…
Because error.tsx renders inside the layout at the same level. If that layout itself is broken, it cannot wrap its own error UI. How to handle it: - An error in app/dashboard/layout.tsx needs the parent-level app/error.tsx to catch it. - An error in the root…
These are constants exported at the top of page.tsx/layout.tsx/route.ts to force rendering and caching behavior for the whole segment. - dynamic: 'auto' (default) · 'force-dynamic' re-renders on every request, effectively opting out of all caching · 'force-static' forces static rendering, with dynamic APIs like cookies()…
They solve two different problems. Server Action — mutations originating from your own UI: - Binds directly to <form action={...} or is called from a client component; no hand-written fetch plus endpoint. - Works even before JS loads (progressive enhancement with forms). - After writing,…
No. generateStaticParams only decides which set is prerendered at build time; the rest can be rendered on first visit and cached afterwards. Common strategy: prebuild the important set, leave the long tail on demand. With dynamicParams = true (the default), slug 1001 is rendered on…
Next.js lets pages/ and app/ coexist in one project, so migrate incrementally instead of rewriting at once. But a path can live on only one side: if pages/about.tsx and app/about/page.tsx both exist, next build fails with a conflict error. So when you move a page,…
Next.js splits environment variables into two clear groups: - No prefix (DATABASEURL, STRIPESECRETKEY): server-only — Server Components, Route Handlers, Server Actions. Reading them on the client yields undefined. - NEXTPUBLIC prefix (NEXTPUBLICGAID): inlined into the source at build time and shipped inside the JavaScript bundle…
The difference is whether the address bar changes. - redirects: the server returns a 3xx, the browser navigates to the new URL, and the address bar changes. Both users and Google learn the page moved. - rewrites: the server quietly serves the content of another…
That error is a safety mechanism: if any domain could be optimized, anyone could make your server process their images. You must declare the allowed hosts: Keep the pattern as narrow as possible (pathname, port). Avoid hostname: ''. fill and sizes: when the intrinsic size…
The error happens because Next.js renders that component on the server (Node), where window/document do not exist. Chart, editor, and map libraries often touch the DOM at import time. ssr: false tells Next.js to skip the component during server rendering and mount it only on…
Three causes cover most cases: 1. The image URL is relative. Social crawlers need an absolute URL. Declare metadataBase once in the root layout and Next.js prefixes everything for you: Without metadataBase the emitted tag is /og.png, which the crawler cannot resolve. 2. Metadata is…
No. The sitemap standard caps a single file at 50,000 URLs or 50MB uncompressed. Beyond that, Search Console reports a sitemap-over-limit error and there is no guarantee Google reads the first part of the file. Building a 200,000-element array in one function also risks running…
The App Router removed automatic i18n config and expects you to build routing yourself with a dynamic segment: Three pieces to wire up: 1. proxy.ts for locale selection (since Next.js 16, middleware.ts is renamed to proxy.ts). When a request hits / with no locale, read…