Host a Next.js site

Serve a Next.js app on the Node.js application with standalone output, a build-on-install step, and a tiny launcher — the exact recipe, and why each piece has to be there.

Skip the setup This guide has a one-click starter template that installs everything below onto your server.

Next.js usually runs behind its own dev server, but the Node.js application just runs one entry file. The bridge between the two is Next's standalone output plus a tiny launcher. This guide is the exact, verified recipe to serve a Next.js site on Falix — three small files, and the reason each one exists.

At a glance
You need A Falix server running the Node.js application and a Next.js project (yours, or a fresh create-next-app)
Time Twenty-five minutes, plus build time

If Node on Falix is new to you, read Node.js on Falix first — this builds on its index.js entry file and automatic npm install. A Next.js site is also a natural Git deploy.

The problem, in one line

The Node.js application starts your site by running node index.js. Next.js has no index.js you can run directly — it expects next start behind a build. Standalone output closes that gap: Next can emit a plain-Node server you can run directly.

Three files

Three small files, and the job each one does:

File Job
next.config.js Emit a self-contained standalone Node server
package.json Build on install via postinstall, then copy static/public in
index.js Launcher — set PORT/HOSTNAME, then start the standalone server

1. next.config.js — build a standalone server

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

module.exports = nextConfig;

output: 'standalone' tells Next to produce a self-contained server at .next/standalone/server.js after a build — no framework CLI needed to run it, just node. That's the file the Node application can start.

2. package.json — build during the automatic install

The Node application runs npm install on every start when a package.json exists. Hook the build onto that with a postinstall script:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "postinstall": "next build && cp -r .next/static .next/standalone/.next/"
  }
}

postinstall runs right after npm install, so every start goes: install dependencies → next build → a fresh standalone server. The cp is not optional: standalone deliberately leaves out .next/static (your compiled CSS and JS chunks), so you copy them in yourself. Skip it and the site loads with no styling at all.

If your project has a public/ folder (create-next-app makes one), mirror it into standalone the same way — this is the standard companion step in Next's own standalone docs:

"postinstall": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/"

3. index.js — the launcher (your Main file)

The Node application runs index.js by default, so name the launcher index.js and leave the Main file variable alone:

process.env.PORT = process.env.SERVER_PORT || 3000;
process.env.HOSTNAME = '0.0.0.0';

console.log(`Listening on port ${process.env.PORT}`);

require('./.next/standalone/server.js');

Next's standalone server reads PORT and HOSTNAME from the environment, so the launcher sets them from Falix's SERVER_PORT and 0.0.0.0 before handing off — the two rules from every web app here, applied to Next. The console.log is there on purpose: the panel flips your server to online when it sees the word Listening, and Next's own ready line doesn't contain it, so printing this turns the status green.

Start it — and expect a wait

Press Start. The console runs npm install, then next build. When it finishes you'll see the Listening line and the standalone server boot. Open your server's address from the Network page and the site loads.

💡 Tip: Building a site takes real time, so the first start is slow and can look like it's hanging. It isn't; watch the build output scroll by.

🎯 Good to know: Because the build lives in postinstall, it reruns on every start. That's the simplest setup, but it means every restart rebuilds.

Environment variables and API routes

Two things people always ask about Next carry over here unchanged.

Environment variables. Next reads them from .env files in your project. Anything the browser needs to see must be prefixed NEXT_PUBLIC_ (for example NEXT_PUBLIC_API_URL); Next inlines those at build time, so the .env has to be present when next build runs — which in this setup is on the server during postinstall. Names without the prefix stay server-only. Keep real secrets out of Git and out of NEXT_PUBLIC_ names — see Keep secrets out of Git.

API routes. Route handlers (app/api/**/route.js or pages/api/**) are bundled straight into the standalone server and answer on the same public port as your pages — no separate service and no extra config.

Deploying from Git

A Next.js project is a natural fit for Deploy from Git. If you'd rather not rebuild on every start, move next build out of postinstall and into a post-deploy command so it runs once per deploy instead — see Build steps on deploy. Leave the launcher and next.config.js exactly as they are; only where the build runs changes.

Troubleshooting

  • Page loads but has no styling — the static copy step is missing or failed. Confirm postinstall ends with cp -r .next/static .next/standalone/.next/ and that it ran cleanly in the console.
  • Images or files in public/ return 404 — you didn't copy public/ into standalone. Add the companion cp -r public .next/standalone/.
  • Start seems stuck for minutes — it's building. next build is the slow part; let it finish. A larger site simply takes longer.
  • Killed mid-build (exit code 137)next build ran out of memory, common on big sites and tight on free's 2.5 GB shared RAM. See Out of memory; a plan with more RAM builds reliably.

Next steps

Was this guide helpful?