# Deploy Next.js

Next.js deploys in one of two shapes, and detection picks the right one from your `next.config.js`:

| Shape | When | Serves from |
| --- | --- | --- |
| **Server-rendered** (default) | Anything with server code: SSR, API routes, server actions | A container behind the edge CDN |
| **Static export** | `output: 'export'` in the config | The CDN only - no server at all |

## Server-rendered

Push a Next.js repo and it builds into a container (generated image on Node 22, listening on port `3000`).

Server-rendered frontends run under [the SSR policy](/create/scaling#the-ssr-policy): pinned to the **Micro** size, scaling 0-3, in a tier-1 region, always behind the edge CDN. The edge serves your audience; the origin only renders cache misses, so a bigger origin would buy nothing.

Things to know:

- **Port.** The server must listen where the platform routes - the generated setup handles it, and `next start` respects the `PORT` [variable](/create/build-settings#port), which is set for you.
- **Runtime configuration.** Server code reads `process.env` at runtime as usual - set values as [environment variables](/platform/environment-variables), per environment.
- **Build-time inlining.** Container images are [built without your runtime variables](/platform/deployments/builds#environment-variables-at-build-time), so `NEXT_PUBLIC_*` values are inlined from what exists at image build, not from the environment's variable set. Read configuration server-side at runtime where you can; if the client bundle must carry environment-specific values, prefer the static export shape, whose build runs with the variables set.

## Static export

Set the export mode in `next.config.js`:

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

module.exports = nextConfig;
```

The build writes plain files into `out`, and that folder is served from the CDN - [free bandwidth](/billing/pricing#static-sites), no region, no cold starts, no instance to pay for. `NEXT_PUBLIC_*` variables work normally here, because [static builds run with the environment's variables set](/platform/environment-variables#build-time-and-runtime).

Static export drops the server features: no SSR, no API routes, no server actions. If you need an API next to a static frontend, deploy it as its own [backend app](/platform/frameworks#backend) - a monorepo with two apps and two [root directories](/create/application-settings#root-directory) works well.

## Which shape to pick

- Content sites, docs, dashboards against an external API: **static export**. Cheapest and fastest.
- Apps that render per-request, use API routes, or need server actions: **server-rendered**.

You can switch later - change the config, push, and detection follows.

## Related

- [Frameworks](/platform/frameworks): Everything supported and how detection works.
- [Scaling](/create/scaling): The SSR policy and what scale to zero means.
- [Environment variables](/platform/environment-variables): Build-time vs runtime values, in detail.
