Setting output: 'standalone' in next.config makes next build produce a .next/standalone folder containing a minimal server.js and only the node_modules files your app actually uses. You can copy that folder to a server and run node server.js without a full npm install. The catch that trips everyone up: it does not include your public folder or .next/static, so you must copy those in yourself. This guide explains what gets generated, the exact commands and when standalone is worth it.
How to enable it
Add one line to your config:
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
};
export default nextConfig;
Then build as usual:
npm run build
What the build produces
After the build, you have:
.next/
standalone/
server.js <- minimal Node.js server
package.json
node_modules/ <- only the traced files your app needs
.next/
server/ <- compiled server code
static/ <- client JS, CSS and media (NOT inside standalone)
public/ <- your public files (NOT inside standalone)
Next.js uses output file tracing to follow every import and require from your server code and copies only those files into standalone/node_modules. A project whose full node_modules is very large typically ends up with a far smaller standalone folder, because development tools, build tools and unused packages are left out.
Why public and .next/static are missing
The Next.js team leaves these out on purpose, because many setups serve static files from a CDN instead of the Node.js server. If you want server.js to serve them (the normal case on a single server), copy them in after the build:
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
If you forget this step, pages render but look unstyled, client-side JavaScript fails to load (404s on /_next/static/...) and images from public are missing. That is the most common standalone bug by far.
A convenient approach is to put it in your build script:
{
"scripts": {
"build": "next build && cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/",
"start": "node .next/standalone/server.js"
}
}
These commands assume a Linux or macOS shell, which is what build servers use. On Windows, run them in Git Bash or WSL, or use a small Node.js script with fs.cpSync.
Running server.js
Start the server with Node.js directly:
PORT=3000 HOSTNAME=0.0.0.0 node .next/standalone/server.js
PORTsets the port (default 3000).HOSTNAMEsets the address to bind to. Inside containers and on most platforms you want0.0.0.0so traffic from outside the process can reach it.
Do not use next start with standalone output. It prints a warning because standalone apps are meant to run through server.js.
Environment variables work as normal: server-side values are read from process.env at runtime, and NEXT_PUBLIC_ values were already inlined at build time. See Next.js environment variables in production for the details.
Image optimisation and sharp
Since Next.js 15, sharp is used automatically for image optimisation with standalone output, so you no longer need to install it manually. If you customised your image setup, check Next.js image optimisation when you self-host.
Standalone in a monorepo
In a monorepo (Turborepo, npm workspaces, pnpm workspaces), packages often live outside the app folder. Tell Next.js where the repository root is so tracing can include them:
// apps/web/next.config.js
const path = require("node:path");
module.exports = {
output: "standalone",
outputFileTracingRoot: path.join(__dirname, "../../"),
};
The standalone folder then mirrors your repository layout, so server.js ends up at .next/standalone/apps/web/server.js, and static files go to .next/standalone/apps/web/.next/static. Adjust your copy commands and start command to match.
When tracing misses a file
Tracing only sees files your code imports. Files loaded by path at runtime, such as a Prisma engine, a font file read with fs, or a JSON file loaded dynamically, can be missed. Add them explicitly:
module.exports = {
output: "standalone",
outputFileTracingIncludes: {
"/api/report": ["./templates/**/*"],
},
};
There is a matching outputFileTracingExcludes for files that get pulled in but are not needed. Both options are top-level config keys (they moved out of experimental in Next.js 15). The output docs list them in full.
A minimal Dockerfile
Standalone output is what makes small Next.js container images practical:
FROM node:24-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:24-alpine
WORKDIR /app
ENV NODE_ENV=production PORT=3000 HOSTNAME=0.0.0.0
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
USER node
EXPOSE 3000
CMD ["node", "server.js"]
Should you use standalone?
| Use standalone when | Stick with next start when |
|---|---|
| You build Docker images and want them small | Your host installs dependencies and runs npm start for you |
| You deploy by copying a build artefact to a server | You deploy from Git and the build happens on the server |
| You want fast cold starts on container platforms | You prefer the simplest possible setup |
On managed Node.js hosting that builds from Git, both approaches work. On NewHost you set the start command yourself, so a standalone app uses node .next/standalone/server.js (with the copy step in your build script), while a regular app uses npm start.
Frequently asked questions
Why is my standalone Next.js app unstyled?
Because .next/static was not copied into .next/standalone/.next/static. The HTML loads but the CSS and JavaScript files return 404. Copy the folder after each build.
Does standalone output make my app faster?
Not at request time, because it is the same Next.js server. It makes deployments smaller and faster to copy and start, which matters most for containers.
Can I use standalone output with the App Router?
Yes. Standalone works with the App Router, Pages Router, Server Actions, ISR and image optimisation. It only changes how the build is packaged.
Where do I put my .env file with standalone output?
Preferably nowhere. Set environment variables in your hosting environment or container. NEXT_PUBLIC_ values must be present at build time, and server-side values must be present when server.js starts.
Want to deploy a standalone or standard Next.js build from Git to South African servers? See NewHost Next.js hosting, or deploy a Next.js app from GitHub step by step.