Guide

Deploy a Next.js app on Swiss hosting with klickops

6 min read nextjsdeploymentswiss hostingpostgresql

Next.js is usually shown running on Vercel, but it is at heart a Node server, and it runs anywhere a container runs. That matters if your users, your customers' lawyers or your own principles say the app should live in Switzerland. This guide walks through deploying a production Next.js app on klickops: building it right, getting it live, wiring a domain and a database, and understanding what autoscaling and scale to zero mean for a server-rendered app.

Build with standalone output

By default, a Next.js production build expects the whole node_modules tree at runtime, which makes for slow deploys and bloated images. Standalone mode traces exactly which files the server needs and copies them into one self-contained folder with its own minimal server.js. One line in the config turns it on:

After next build, everything the app needs at runtime is in .next/standalone, plus the static assets in .next/static and your public folder. That trio is your deployable unit, and it typically shrinks the image by hundreds of megabytes.

next.config.js
module.exports = {
	output: "standalone"
};

Two ways to deploy

The fastest path is to connect your GitHub or GitLab repository in klickops. Every push builds and deploys automatically, and you can get per-branch preview environments for pull requests. You write no pipeline configuration; the platform starts at your repo and ends at a running app with a URL.

If you would rather own the build, ship a container image instead. klickops deploys any image it can pull, and when you deploy one it inspects the image to suggest the port and environment it exposes. A multi-stage Dockerfile for standalone Next.js looks like this:

Dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

Environment variables, the Next.js way

Next.js splits configuration into two worlds and it pays to respect the split when you wire things up. Variables prefixed NEXT_PUBLIC_ are inlined into the client bundle at build time, so they must exist when the build runs and they are visible to anyone with a browser. Everything else is read by the server at runtime and stays private.

On klickops, set runtime values as environment variables on the app, and store anything sensitive (database URLs, API keys, auth secrets) as managed secrets instead: they are injected into the container at runtime and the dashboard never displays the value again after you save it. Because NEXT_PUBLIC_ values are baked in at build time, changing one means rebuilding, which the connect-a-repo flow does for you on the next push.

A domain with TLS you never think about

Every app gets a platform subdomain with working HTTPS the moment it deploys, which is all you need for staging and previews. For production, add your own domain in the dashboard, point a DNS record at it, and klickops issues and renews the TLS certificate automatically. There is no certbot, no certificate resource to manage and no renewal cron to forget.

One planning note: the free plan runs on the platform subdomain only. Custom domains start with the Hobby plan (CHF 9 per month), which includes three of them.

What autoscaling and scale to zero mean for Next.js

A server-rendered Next.js app is a long-running process, and klickops treats it like one. Autoscaling adds replicas when load rises and removes them when it falls, with zero-downtime rollouts when you deploy. CPU and memory are auto-sized, so you never pick an instance type; billing meters what the app actually uses, hour by hour.

Scale to zero takes that to its logical end: when the app has no traffic, it can stop running entirely, and with usage-based billing a stopped app accrues no compute cost. The trade-off is honest and worth knowing: the first request after a sleep waits for the container to start, which for a standalone Next.js server is typically a few seconds. That is a fine deal for staging environments, internal tools and side projects, and the wrong one for a latency-sensitive production homepage, where you would keep at least one replica warm and let autoscaling handle the peaks.

Add managed Postgres

Most real Next.js apps grow a database, and this is where running on a platform beats stitching services together. Create a managed PostgreSQL instance in the same project: it comes with high availability, automated backups, point-in-time restore and a query console, and it runs in the same Swiss data centre as your app, so queries never cross a border or the public internet.

Copy the connection string into a secret (DATABASE_URL), reference it from the app, and your ORM works unchanged. Prisma, Drizzle and friends need no special configuration beyond the URL.

What it costs, roughly

Because billing is metered, cost tracks the app's real footprint rather than a plan tier's shape. A production Next.js app plus a small Postgres instance averaging around 0.4 vCPU, 1.5 GB of memory and 10 GB of disk works out to roughly CHF 43 per month at list rates, and plan credit brings the real bill below that (each plan includes usage credit worth more than the plan price). A hobby project that sleeps most of the day lands far lower, and the free plan covers one small app and one database inside a small envelope, with no card.

The pricing calculator on the pricing page uses the same live rates if you want to model your own numbers before deploying anything.

Why this beats a VPS for Next.js

You could run the same container on a rented VPS, and plenty of people do, right up until the certificate renewal fails on a weekend or the box needs a kernel patch. On klickops the platform handles TLS, rollouts, rollbacks, scaling, backups and monitoring, while everything underneath stays standard: your app is a plain Kubernetes Deployment you can export as clean YAML and take anywhere. Swiss data residency on hardware the operator owns, with none of the server homework, and no lock-in holding you there.

Ready to try it on Swiss infrastructure?

Private beta, free plan for one small stack, no card required.

Join the waitlist