skip to content

A Next.js App Router team sets `output: 'export'` in next.config so the app can be deployed to a plain static file host. Which capabilities stop working, and what has to change in the code?

level: middleimportance: should knowfreq 50%

answer

  1. no process runs after the build
  2. request-time features all disappear
  3. every route must be known at build
  4. dynamic segments need full enumeration
  5. host config replaces framework routing rules

basics

~20 s

Static export emits plain files into out/ with no server at runtime, so anything needing a request or a live server is gone: middleware, Server Actions, cookies/headers, draft mode, ISR and revalidation, and the default image optimizer. Every dynamic route must be enumerated at build time.

solid answer

~50 s

`output: 'export'` makes `next build` write a fully static site into `out/` and there is no Node process afterwards, so every server-dependent feature is unsupported. That means no middleware, no Server Actions, no `cookies()`, `headers()` or `draftMode()`, no route handlers that depend on the incoming request, no incremental static regeneration or on-demand revalidation, and no rewrites, redirects or headers from `next.config` — those become the static host's configuration instead. Dynamic segments must be fully enumerated with `generateStaticParams`, with `dynamicParams` false, because there is nothing to render an unknown slug at request time. The default image optimizer needs a server too, so you set `images.unoptimized` or point at an external loader. What survives is everything client-side: client components, browser fetching to an external API, and build-time metadata. It is the right target for docs and marketing sites, and the wrong one for anything personalized.

code

javascript · 6 lines
javascript
// next.config.js
module.exports = {
  output: 'export',
  trailingSlash: true,
  images: { unoptimized: true },
}

go deeper

for a junior

Know that a static export produces plain files with no server, so features that need a request — middleware, Server Actions, cookies — are unavailable and every page must exist at build time.

for a middle

Explain the grouping: request-time features, post-build regeneration, framework routing rules and image optimization all depend on a running server, and enumerate what code must change, starting with generateStaticParams and dynamicParams.

for a senior

Judge fit rather than reciting limits — recognise when a product's personalization or freshness requirements rule the export out, and know that auth in an export is client-side gating only, with real enforcement at the API.

for a principal

Own the call and its exit cost: choosing export trades operational simplicity for a hard ceiling, and you should be able to say in advance what change in requirements forces a migration and what that migration would cost.

## What the mode actually produces With `output: 'export'` set in `next.config`, `next build` produces an `out/` directory of HTML, CSS, JavaScript and the React Server Components payload files, ready to be uploaded to any host that can serve files. There is no runtime process afterwards. That single fact explains the entire unsupported list — you are not choosing a smaller feature set for taste, you are removing the thing that implemented half the framework's features. A version note: this is configured through `output: 'export'` in `next.config`; the separate `next export` CLI command was removed in Next.js 14. ## What stops working, grouped by why **Needs a request at runtime.** Middleware never runs — there is no process to run it in. Server Actions cannot be invoked, because an action is an RPC endpoint on a server. `cookies()`, `headers()` and `draftMode()` have no request to read. Route handlers that depend on the incoming request cannot be served. **Needs a server after the build.** Incremental static regeneration and on-demand revalidation both mean "re-render this page later"; there is no later. A page's content is whatever the build produced, until the next build. **Needs the framework's server to intercept the URL.** `rewrites`, `redirects` and `headers` declared in `next.config` are behaviours of the Next server. In a static export they are simply absent, and the equivalent has to be expressed in the host's own configuration. **Needs an optimizer process.** The default image optimization loader transforms images on request. In an export you either set `images: { unoptimized: true }` and ship the originals, or configure a custom loader that points at an external image service. **Needs runtime routing decisions.** A dynamic segment such as `app/blog/[slug]/page.tsx` must have a `generateStaticParams` that enumerates every slug at build time, and `dynamicParams` must be false — there is no fallback path that renders an unknown slug on demand. Intercepting routes, which depend on server-side routing, are likewise out. ## What still works A lot, which is why the mode is useful. Server Components still run — at build time, producing static output. Layouts, route groups, `generateMetadata` and `generateStaticParams` all work. Client components work normally in the browser, including fetching from an external API at runtime, client-side state, and interactivity. Authentication becomes an entirely client-side concern: you can gate UI in the browser against a token, but you have no server-side guard, so anything genuinely sensitive must live behind the API you are calling, not behind the page. ## Details that bite at the host The `trailingSlash` option changes whether the export emits `about.html` or `about/index.html`, which decides whether a given static host resolves `/about` without extra rewrite rules. Getting this wrong produces 404s on direct navigation that never appear in local testing, because the local preview resolves paths more leniently than the eventual host does. Test the export against the real host early. ## How to reason about the choice Static export is a genuine deployment target with a real payoff: no server to operate, no scaling story, trivially cacheable output, and hosting that is close to free. It fits documentation, marketing sites, and environments where only object storage is available. The mistake is adopting it for an app that will need personalization or mutation later. Adding a single logged-in view, a form that writes, or a page that must reflect data within minutes means either abandoning the export or re-implementing the missing half in client code against a separate backend — often at more total cost than running a Node server would have been. Decide it deliberately: if the site is content that changes on a build cadence, export is excellent; if the site is an application, it is not the target.

  • A statically exported Next.js site needs a contact form that stores submissions. How do you do it?
    Post from a client component to an API you host separately — a serverless function, a form service, or your own backend — and handle the response in the browser. Server Actions and route handlers are not available in an export, so the form cannot submit to the Next app itself; the Next side is just the client code that calls out.
  • Can a statically exported Next.js site still use Server Components?
    Yes, but they run only at build time. They fetch and render during `next build`, and the result is baked into the emitted HTML and RSC payload. What you lose is per-request execution: they cannot read cookies or headers, and their data is as fresh as the last build, which is why content updates require a rebuild and redeploy.
  • How do you keep a statically exported marketing site reasonably fresh without moving off the export?
    Trigger a rebuild-and-deploy when content changes — typically a webhook from the CMS into CI. The freshness ceiling is your build-and-deploy time, so it fits content that changes hourly or daily. If the requirement drifts toward seconds or toward per-user content, that is the signal the export is the wrong target.

saying these in an interview costs you the question

  • Thinks middleware still runs on a statically exported site
  • Expects revalidate to refresh pages after the build
  • Assumes dynamic segments fall back to on-demand rendering
  • Believes Server Actions work without a server
  • Treats client-side auth checks in an export as real protection

context