How to Deploy a Next.js App on cPanel Shared Hosting (Step-by-Step Guide)
Deploying a Next.js application on cPanel shared hosting can feel tricky at first, because shared hosting was originally designed for PHP websites — not Node.js apps. The good news? It is absolutely possible, and once you understand the process, it becomes simple and repeatable.
In this guide, I'll walk you through two proven methods to deploy your Next.js app on cPanel: Static Export (the easiest and most reliable) and the Node.js Application method (for apps that need server-side rendering and API routes). Let's dive in.
Before You Start: Understand Your App Type
The deployment method you choose depends entirely on how your Next.js app works. Ask yourself these questions:
- Does my app use API routes (
app/apiorpages/api)? - Does my app use Server-Side Rendering (SSR) with
getServerSidePropsor dynamic server components? - Does my app use Incremental Static Regeneration (ISR)?
- Does my app use next/image with the default image optimization?
If you answered "No" to all of these, your app can be exported as a static site — and Method 1 is perfect for you. If you answered "Yes" to any of them, you'll need Method 2, which requires your hosting provider to support the "Setup Node.js App" feature in cPanel.
Method 1: Deploy Next.js as a Static Site (Recommended for Most Users)
This is the cleanest and most stable way to run a Next.js site on shared hosting. Your app is converted into plain HTML, CSS, and JavaScript files — exactly what shared hosting servers love to serve. It's fast, cheap, and nearly impossible to break.
Step 1: Enable Static Export in next.config.js
Open your next.config.js (or next.config.mjs) file and add
the output: 'export' option:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true, // required, because image optimization needs a server
},
trailingSlash: true, // helps cPanel serve pages as folders with index.html
};
module.exports = nextConfig;
Why unoptimized: true? The default
next/image component optimizes images on a Node.js server at request
time. Since a static export has no server, this option tells Next.js to serve
images as-is.
Why trailingSlash: true? It makes Next.js generate
/about/index.html instead of /about.html, which matches
how Apache (the web server behind cPanel) naturally resolves URLs. This prevents
404 errors when users refresh a page.
Step 2: Build Your Project
Run the build command in your project folder:
npm run build
When the build finishes, Next.js creates a folder called out in your
project root. This folder contains your entire website as static files — this is
what you'll upload to cPanel.
Step 3: Compress the "out" Folder
Open the out folder, select all files and folders inside it
(not the folder itself), and compress them into a ZIP file. This small detail matters:
if you zip the folder itself, your files will end up in
public_html/out/ instead of public_html/, and your site
won't load at your domain root.
Step 4: Upload to cPanel
- Log in to your cPanel dashboard (usually
yourdomain.com/cpanel). - Open File Manager.
- Navigate to the public_html directory (or the folder assigned to your domain/subdomain).
- Delete any default files like
index.htmlordefault.htmlplaced by your host. - Click Upload and select your ZIP file.
- Once uploaded, right-click the ZIP file and choose Extract.
- Delete the ZIP file after extraction to keep things clean.
Step 5: Add an .htaccess File (Fix 404 and Routing Issues)
Create a file named .htaccess inside public_html and add
the following rules. This ensures clean URLs work correctly and adds basic caching
for better performance:
RewriteEngine On
# Serve existing files and directories directly
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Try the .html version of the requested path
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [L]
# Custom 404 page generated by Next.js
ErrorDocument 404 /404.html
# Browser caching for static assets
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
Tip: If you can't see the .htaccess file in File Manager,
click Settings (top-right corner) and enable
"Show Hidden Files (dotfiles)".
Step 6: Test Your Website
Visit your domain in the browser. Click through your pages, refresh a few inner pages directly, and confirm everything loads. If you see your homepage — congratulations, your Next.js site is live! 🎉
Method 2: Deploy Next.js with SSR Using cPanel's Node.js App Feature
If your app needs API routes, server-side rendering, or ISR, you need a running Node.js server. Many modern shared hosting providers (especially those using CloudLinux) offer a feature called "Setup Node.js App" in cPanel. If you don't see it in your cPanel, contact your host — or consider upgrading to a plan that includes it.
Step 1: Prepare a Custom Server File
cPanel's Node.js manager (Phusion Passenger) needs an entry file to start your app.
Create a file named server.js in your project root:
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const port = process.env.PORT || 3000;
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
}).listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
Step 2: Build Your App Locally
npm run build
This generates the .next folder containing your production build.
Building locally is strongly recommended — shared hosting servers often have
limited memory, and next build can easily exceed those limits and fail.
Step 3: Upload Your Project Files
Create a folder outside public_html (for example,
/home/youruser/nextjs-app) and upload these items (zip them first for
faster upload, then extract):
- The
.nextfolder (your production build) - The
publicfolder package.jsonandpackage-lock.jsonserver.jsnext.config.js
Do not upload node_modules. It's huge, slow to upload,
and may contain binaries compiled for the wrong operating system. You'll install
dependencies on the server instead.
Step 4: Create the Node.js Application in cPanel
- In cPanel, open Setup Node.js App.
- Click Create Application.
- Node.js version: Choose 18.x or higher (20.x recommended for Next.js 14+).
- Application mode: Production.
- Application root: The folder where you uploaded your files (e.g.,
nextjs-app). - Application URL: Select your domain or subdomain.
- Application startup file:
server.js - Click Create.
Step 5: Install Dependencies
On the same Node.js App page, scroll down and click
"Run NPM Install". cPanel will read your package.json
and install everything on the server. This may take a few minutes.
Alternatively, if you have SSH access, activate the virtual environment (cPanel shows the exact command at the top of the app page) and run:
source /home/youruser/nodevenv/nextjs-app/20/bin/activate
cd ~/nextjs-app
npm install --production
Step 6: Add Environment Variables
In the Node.js App interface, use the "Add Variable" button to add
your environment variables — the same ones from your local .env.local
file, such as:
NODE_ENV=productionDATABASE_URL= your database connection stringNEXT_PUBLIC_SITE_URL=https://yourdomain.com
Important: Variables prefixed with NEXT_PUBLIC_ are
baked in at build time. If you change them, you must rebuild locally and
re-upload the .next folder.
Step 7: Restart and Test
Click "Restart" on the Node.js App page, then open your domain in the browser. Your server-rendered Next.js app should now be live, complete with working API routes.
Common Problems and How to Fix Them
1. "404 Not Found" on Page Refresh (Static Export)
This means Apache can't map the URL to a file. Double-check your
.htaccess rules and make sure you enabled
trailingSlash: true before building.
2. "503 Service Unavailable" (Node.js Method)
Your app crashed on startup. Check the stderr.log file inside your
application root folder. The most common causes are a missing dependency (run NPM
Install again), a wrong startup file name, or an unsupported Node.js version.
3. Images Not Loading
For static exports, confirm you set images: { unoptimized: true }.
Also check that image paths are relative to your domain root and that filenames
match exactly — Linux servers are case-sensitive, so
Logo.png and logo.png are different files.
4. Build Fails on the Server with "Killed" or Memory Errors
Shared hosting typically limits processes to 512MB–1GB of RAM, while
next build often needs more. The fix: always build locally and upload
the .next folder — never build on the server.
5. Changes Not Showing After Re-Upload
Clear your browser cache, and if you're using the Node.js method, always click Restart after uploading new files. Passenger caches the running app until it's restarted.
Updating Your Site After Deployment
Your update workflow is simple:
- Make your changes locally.
- Run
npm run build. - Static method: Upload and extract the new contents of the
outfolder intopublic_html, replacing the old files. - Node.js method: Upload the new
.nextfolder (delete the old one first), then click Restart in the Node.js App panel.
Pro tip: To avoid downtime during static updates, upload the ZIP first, then delete old files and extract — the swap takes seconds instead of minutes.
Static Export vs. Node.js App: Which Should You Choose?
| Feature | Static Export | Node.js App |
|---|---|---|
| Setup difficulty | Very easy | Moderate |
| API routes | Not supported | Supported |
| SSR / ISR | Not supported | Supported |
| Speed on shared hosting | Excellent | Good |
| Server resource usage | Minimal | Moderate to high |
| Works on every cPanel host | Yes | Only with "Setup Node.js App" |
My honest advice as a Next.js developer: if your site is a blog, portfolio, company website, or landing page, use the static export method. It's faster, more secure, and immune to server crashes. Reserve the Node.js method for apps that genuinely need a live server — and if your app grows beyond what shared hosting can handle, platforms like Vercel or a small VPS are the natural next step.
Final Thoughts
Deploying Next.js on cPanel shared hosting is entirely achievable once you match the right method to your app's needs. Static export gives you a bulletproof, lightning-fast site on any host, while the Node.js App feature unlocks full server-side power on hosts that support it. Follow the steps above, keep the troubleshooting section handy, and you'll have your app live in under an hour.
Happy deploying! If you hit an issue not covered here, check your hosting provider's documentation for Node.js support — or drop a comment below and I'll help you debug it.

Comments
No comments yet.