Static Export

Setting output: 'export' in next.config.js tells next build to produce a plain folder of static files -- HTML, CSS, JavaScript, and other assets -- instead of the hybrid server output used by self-hosting or Vercel. There is no Node.js server involved at runtime at all: the output can be served by literally any static file host, exactly like a folder of hand-written HTML files.


next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
}

module.exports = nextConfig

terminal:
next build
# static site is written to ./out

What Becomes Unavailable

Every feature that depends on code running on a live server at request time is off the table, because there is no server to run it. Attempting to use most of these while output: 'export' is set causes next build to fail with an explanatory error rather than silently producing a broken build.

Dynamic routes still work, but every possible value has to be known and enumerated at build time via generateStaticParams, since there is no server left to render an unlisted value on the fly.


app,blog,[slug],page.tsx:
export function generateStaticParams() {
  return [{ slug: 'first-post' }, { slug: 'second-post' }, { slug: 'third-post' }]
}

export default function Page({ params }: { params: { slug: string } }) {
  return <article>{params.slug}</article>
}


When It Makes Sense

Static export is a good fit whenever the entire site can be fully determined at build time: marketing pages, documentation, blogs backed by markdown or a headless CMS fetched during the build, and internal tools where a rebuild-and-redeploy cycle for content changes is perfectly acceptable. It's a poor fit for anything that needs personalized responses, real-time data, or server-side auth checks on every request.

Because the output is just static files, it can be deployed to hosts that have no concept of a Node.js runtime at all: GitHub Pages, Amazon S3 (optionally behind CloudFront), or any plain static hosting bucket. It's also the simplest possible deployment target among the other platforms covered elsewhere in this chapter -- there's no adapter to install because there's no server-side behavior for an adapter to reproduce.



Configuring It

Two settings come up often enough to be worth calling out directly. basePath is required when the site is served from a subpath rather than the domain root -- for example, a GitHub Pages project site served at username.github.io/my-docs-site rather than a custom domain. images.unoptimized avoids the build-time error that would otherwise occur from using the default image loader without a server behind it.


next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  basePath: '/my-docs-site',
  images: {
    unoptimized: true,
  },
}

module.exports = nextConfig