Key Takeaways
- Static exports break Next.js’s dynamic features — API routes, middleware, live data fetching, and image optimization all require a real, running server.
- Serverless hosting introduces cold starts, while a persistent Node.js server stays warm and responds instantly on every request.
- Cloudways Velocity auto-detects the Next.js SSR framework preset from your package.json, so you can deploy straight from GitHub without configuring Nginx, PM2, or SSL yourself.
- The full demo project — a live Tech News Dashboard built with a Next.js Server Component — is available on GitHub to clone and reuse.
Developing a Next.js application locally is the fun part. You run npm run dev, open localhost:3000, and everything just works. Hot module replacement is instant. Server-side rendering acts exactly how you expect. API routes fire without a hitch.
Pushing that code live to production is a totally different story. You almost always hit a wall of frustration.
When it is time to deploy Next.js, the entire industry points toward using serverless platforms. Serverless architecture is perfect for side projects, but the second you try to put a real-world, dynamic application into production, you run into a massive issue: cold starts.
If you want complete control over your hosting environment, you do not want backend instances going to sleep. A 3-second latency spike on the initial page load just because nobody visited the site in the last five minutes ruins the entire user experience.
For this blog, I want to build a clean Next.js App Router project and push it live to a persistent Cloudways Velocity Node.js environment. No serverless cold starts. No sleeping instances.
Static Export vs. Server-Side Rendering in Next.js
Before touching the terminal, let’s clear up a massive misconception about deploying Next.js apps. Browsers are inherently dumb. Out of the box, Chrome and Safari only know how to read raw HTML, CSS, and plain JavaScript. They have absolutely no idea what a React Server Component is. They cannot execute Node.js backend logic.
Because of this limitation, a lot of developers try to take the easy way out. They force Next.js into a static export by dropping output: ‘export’ into the next.config.js file.
Running a build command with this setting strips away the backend entirely. Next.js renders all the pages ahead of time and spits out a folder full of flat, static HTML files. You can then take that folder and toss it onto literally any cheap static web host.
But doing this fundamentally breaks the exact tools that make Next.js powerful. Here is how the two environments compare:
| Next.js Feature | Static Export (output: ‘export’) | Persistent Node.js Server |
| API Routes | Broken. No server to process requests. | Fully supported and dynamic. |
| Middleware | Broken. Request interception fails. | Fully supported. |
| Data Fetching | Cached permanently at build time. | Fetches real-time data on every request. |
| Image Optimization | Fails unless using a third-party loader. | Works natively via the Next.js server. |
By forcing a static export, you instantly lose access to dynamic API routes. You cannot have server-side endpoints processing form data or handling secure authentication. Request interception and redirects happen at the server level, meaning middleware is dead.
If an app relies on fetching live database information on every single page request, a static export just displays stale data from the exact moment the build was run.
For a modern, dynamic application, static hosting is completely off the table. It requires a real, running server.
Why Deploy Next.js on a Node.js Server?
Since a server is strictly required, the debate always comes down to Serverless Functions versus a Persistent Node.js Server.
Serverless environments scale infinitely and charge purely based on compute time. But that pricing model is a trap for consistent user experience. If nobody hits the website for a bit, the provider spins down the backend instance to save money. It goes to sleep.
When a user eventually clicks a link to visit the site, the platform has to wake up the server, boot up the Node.js runtime, load the Next.js application into memory, and then process the request. That is a cold start. It turns an otherwise lightning-fast application into a sluggish mess for that first user. Nothing makes a visitor close a browser tab faster.
This is exactly why moving deployments to a persistent Node.js server makes sense.
A dedicated, persistent Node.js process stays awake 24/7. It does not matter if the site gets one visitor an hour or a thousand visitors a minute; the runtime is already warm and waiting in memory. When a request hits a Cloudways Velocity server, the response is immediate. You get the full benefits of server-side rendering (SSR) on every single request without ever paying the latency penalty of a sleeping instance.
Skip the DevOps, Ship Faster
Cloudways Velocity handles the server administration for you, so you can focus on building instead of managing infrastructure.
Mini Project: Build a Tech News Dashboard
I’m going to build a minimal Tech News Dashboard. I’ll write a custom Next.js Server Component that fetches live data from an external API on the server before sending the rendered HTML to the client.
First things first. I need to set up my local workspace.
I’m using my work laptop with IT restrictions so I can’t run standard installers. Because of this, I downloaded the standalone binary .zip version of Node.js.
And since my Command Prompt has no idea where Node lives on my machine, before I can even scaffold the project, I have to tell CMD where my Node folder is.
I will open Command Prompt and run this command:
set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.18.0-win-x64\node-v24.18.0-win-x64
It works perfectly. CMD now executes Node and npm commands. I’ll change directories to my desktop and spin up the new project.
cd C:\Users\abdulrehman\Desktop npx create-next-app@latest
The CLI prompts me with a few configuration questions. Here is exactly how I answer them for this specific project:
- What is your project named? cloudways-nextjs-demo
- Would you like to use TypeScript? Yes
- Would you like to use ESLint? Yes
- Would you like to use Tailwind CSS? Yes
- Would you like to use src/ directory? Yes
- Would you like to use App Router? (recommended) Yes
- Would you like to customize the default import alias? No



Once NPM finishes downloading the dependencies, I navigate into my new project directory:
cd cloudways-nextjs-demo
Writing the Server Component
Because I am utilizing the Next.js App Router, every component inside the app directory is a Server Component by default. This is perfect for what I need to do. Data must be fetched securely on the backend before the user ever sees the page.
I will open up src/app/page.tsx. Clear out all the default Vite-style or Vercel boilerplate code. Drop in my custom script:
// src/app/page.tsx
type NewsItem = {
id: number;
title: string;
url: string;
time: number;
};
// This function runs entirely on the server during the request
async function getTopStories(): Promise<NewsItem[]> {
const res = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json', {
// Next.js caching override to ensure fresh data on every request.
// This physically proves the persistent server is actually executing logic.
cache: 'no-store'
});
if (!res.ok) {
throw new Error('Failed to fetch top stories');
}
const storyIds = await res.json();
const topTenIds = storyIds.slice(0, 10);
// Fetch details for each of the top 10 stories concurrently
const stories = await Promise.all(
topTenIds.map(async (id: number) => {
const storyRes = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
return storyRes.json();
})
);
return stories;
}
export default async function Home() {
const stories = await getTopStories();
return (
<main className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8 font-sans">
<div className="max-w-3xl mx-auto">
<header className="mb-10 text-center">
<h1 className="text-4xl font-extrabold text-gray-900 tracking-tight">
Live Tech News Dashboard
</h1>
<p className="mt-4 text-lg text-gray-600">
Server-rendered live on a persistent Cloudways Node.js environment.
</p>
</header>
<div className="bg-white shadow overflow-hidden sm:rounded-md">
<ul className="divide-y divide-gray-200">
{stories.map((story) => (
<li key={story.id}>
<a href={story.url} target="_blank" rel="noopener noreferrer" className="block hover:bg-gray-50 transition duration-150 ease-in-out">
<div className="px-4 py-4 sm:px-6">
<div className="flex items-center justify-between">
<p className="text-sm font-medium text-blue-600 truncate">
{story.title}
</p>
</div>
<div className="mt-2 sm:flex sm:justify-between">
<div className="sm:flex">
<p className="flex items-center text-sm text-gray-500">
ID: {story.id}
</p>
</div>
<div className="mt-2 flex items-center text-sm text-gray-500 sm:mt-0">
<p className="font-mono">
Published: {new Date(story.time * 1000).toLocaleDateString()}
</p>
</div>
</div>
</div>
</a>
</li>
))}
</ul>
</div>
</div>
</main>
);
}

The logic here is incredibly important. Look closely at the fetch configuration inside my getTopStories() function. By adding { cache: ‘no-store’ }, I am explicitly telling Next.js to skip the build cache entirely.
If I tried to host this on a standard static platform, it would instantly break. It strictly requires a live Node.js process to reach out to the HackerNews API, fetch the array of story IDs, map over them, request the individual payload for each story, compile the HTML, and send it down the wire.
I’ll test it locally by running npm run dev.

It pops up as a clean, Tailwind-styled list of the current top ten tech stories.

My code is ready to ship.
Pushing the Code to GitHub
My code is ready. Now I need a place to host it. I’m deploying this on Cloudways Managed Node.js hosting (Velocity).
I will go to GitHub and create a new repository called cloudways-nextjs-demo. Leaving it public or private works fine either way.

Then I’ll jump back to my CMD, and push the code up:
git init git add . git commit -m "Initial commit: Server-rendered dashboard complete" git branch -M main git remote add origin https://github.com/abdulrehman293/cloudways-nextjs-demo git push -u origin main


With my code sitting safely in version control, it is time to tackle the infrastructure.
Deploy Straight From GitHub
Connect your repository and let Cloudways Velocity auto-detect your Next.js SSR build — no manual server configuration required.
Deploying to Cloudways Velocity
I have manually deployed custom Node.js applications to bare-metal VPS instances before. It involves writing complex Nginx reverse proxy configurations, managing PM2 processes, and dealing with SSL certificate renewals.
Cloudways Velocity skips all this. It provides a managed Node.js environment where all the server administration is done for me.
With that said, I will open the Cloudways console and click Velocity. Then I will click Get Started. I’ll choose the Starter plan for this deployment.
Next, I click Connect Via Git, link my GitHub account and select my cloudways-nextjs-demo repository.

When I select my repo and proceed, Cloudways automatically scans the root of my project looking for a package.json file.
It reads my dependencies, sees next, and automatically selects the Next.js SSR framework preset. I do not have to write custom start scripts or manually install PM2. The platform knows exactly what to do.

Finally, I hit Deploy Now. Cloudways takes over completely. It pulls my code from GitHub. It installs the NPM packages, runs my Next.js build process, and spins up the server.


Once the deployment is complete, I go back to my application’s Overview tab, copy the Application URL and open it in my browser.

My Tech News Dashboard loads instantly. I refresh the page a few times just to be sure.

I am experiencing true server-side rendering on a persistent Node instance. No 404 errors. No cold starts.
Wrapping Up
That wraps up this guide on deploying Next.js. In this blog, I tried to cover exactly why dodging static exports makes sense, and the massive performance benefits you get by keeping your server-side rendering on a persistent Node.js backend.
I showed you how to build a Next.js App Router dashboard that automatically fetches live tech news on a local setup. After that, I pushed the working project to my GitHub and deployed it live using Cloudways Managed Node.js Hosting (Velocity).
The full project is available on my GitHub. Feel free to clone it and use the code as a starting point for your own SSR applications. If you have any questions about the server configuration or the Git deployment process, just let me know in the comments.
Q. Is Next.js still relevant in 2026?
Yes. It is still the heavyweight React framework. The App Router was rocky at first, but it is incredibly solid now. React Server Components give you massive SEO benefits out of the box. Mixing server-rendered data with interactive client UI just makes sense. Enterprise teams and solo developers rely on it daily.
Q. Where can I deploy NextJS?
You have three main routes. Serverless hosts like Vercel scale well but force you to deal with cold starts. Managed Node.js platforms like Cloudways Velocity give you a persistent server without the DevOps nightmare. Or you can rent a bare-metal VPS, set up Docker, configure Nginx, and manage the entire infrastructure yourself.
Q. Can I deploy NextJS on render?
Yes. Render acts as a persistent web server. You just link your GitHub repository. Set your build command to npm run build and your start command to npm start. The platform handles the rest. You can also build a custom Docker image and deploy that directly.
Q. Can I deploy NextJS to GitHub pages?
Technically yes, but it breaks the framework. GitHub Pages only serves static files. There is no Node.js backend. You have to add output: ‘export’ to your configuration file. This spits out plain HTML. You immediately lose dynamic API routes. You lose server-side rendering. You lose middleware. Do not do this unless you are building a basic static portfolio.
Start Growing with Cloudways Today.
Our Clients Love us because we never compromise on these
Abdul Rehman
Abdul is a tech-savvy, coffee-fueled, and creatively driven marketer who loves keeping up with the latest software updates and tech gadgets. He's also a skilled technical writer who can explain complex concepts simply for a broad audience. Abdul enjoys sharing his knowledge of the Cloud industry through user manuals, documentation, and blog posts.