No articles found
Try different keywords or browse our categories
Fix: Next.js 404 on page refresh (Vercel / Nginx) error
Quick fix for Next.js 404 on page refresh in Vercel or Nginx deployments. Learn how to configure proper routing for client-side navigation.
The ‘Next.js 404 on page refresh’ error occurs when navigating to client-side routes directly or refreshing pages in deployed Next.js applications. This happens because the server doesn’t recognize client-side routes and returns a 404 error instead of serving the main index.html file.
How the Error Happens
❌ Error Scenario - Direct Route Access:
// ❌ This works with client-side navigation but fails on refresh
// Navigate to /dashboard directly in browser
// app/dashboard/page.js
export default function DashboardPage() {
return <div>Dashboard Content</div>;
}
When users navigate directly to https://yoursite.com/dashboard or refresh the page, the server looks for a /dashboard route on the server, but in a SPA, all routes should serve the main application file.
✅ Quick Fix - Deployment Configuration
Solution 1: Vercel Configuration (Automatic)
// ✅ Vercel handles this automatically with Next.js projects
// vercel.json (optional, usually not needed)
{
"rewrites": [
{
"source": "/(.*)",
"destination": "/"
}
]
}
For most Next.js projects deployed on Vercel, this is handled automatically. If you’re experiencing issues, ensure your vercel.json doesn’t interfere with Next.js’s automatic routing.
Solution 2: Nginx Configuration
# ✅ Nginx configuration for Next.js SPA
# /etc/nginx/sites-available/yoursite
server {
listen 80;
server_name yoursite.com www.yoursite.com;
location / {
root /var/www/yoursite;
index index.html;
# ✅ Serve index.html for all routes
try_files $uri $uri/ /index.html;
}
# ✅ Handle API routes separately
location /api/ {
proxy_pass http://localhost:3000; # Your Next.js server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
Solution 3: Apache Configuration (.htaccess)
# ✅ Apache .htaccess for Next.js SPA
# .htaccess in your public directory
Options -MultiViews
RewriteEngine On
# ✅ Redirect all non-file requests to index.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [L]
# ✅ Handle API routes separately if needed
RewriteCond %{REQUEST_URI} ^/api/
RewriteRule ^(.*)$ http://localhost:3000/$1 [P,L]
Solution 4: Custom Server Configuration (Node.js)
// ✅ Custom Express server for Next.js
// server.js
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
// ✅ Handle API routes normally
server.use('/api', (req, res) => {
handle(req, res);
});
// ✅ Serve static files
server.use(express.static('public'));
// ✅ All other routes should serve index.html
server.all('*', (req, res) => {
handle(req, res);
});
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
});
Solution 5: Docker Configuration
# ✅ Dockerfile with proper nginx configuration
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine AS production
COPY --from=builder /app/out /usr/share/nginx/html
# ✅ Copy custom nginx config
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# ✅ nginx.conf for Docker deployment
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
# ✅ Handle Next.js routing
location / {
try_files $uri $uri/ /index.html;
}
# ✅ API routes (if using standalone mode)
location /api/ {
proxy_pass http://backend:3000;
}
}
}
Solution 6: Static Export Configuration
// ✅ For static exports, configure next.config.js
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export', // ✅ Generate static export
trailingSlash: true, // ✅ Add trailing slashes to help with routing
// ✅ Handle rewrites for static export
async rewrites() {
return [
{
source: '/:path*',
destination: '/:path*/index.html',
},
];
},
};
module.exports = nextConfig;
# ✅ Nginx config for static export
server {
listen 80;
server_name yoursite.com;
root /var/www/yoursite/out;
index index.html;
# ✅ Handle all routes for static export
location / {
try_files $uri $uri/ @fallback;
}
location @fallback {
rewrite ^.*$ /index.html last;
}
# ✅ Handle static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
} Related Articles
How to Fix Route '/' does not match any routes error
Quick fix for 'Route / does not match any routes' error. Learn how to resolve routing issues in React Router, Next.js, and other JavaScript frameworks.
Fix: useRouter only works in Client Components Error
Learn how to fix the 'useRouter only works in Client Components' error in Next.js applications. This comprehensive guide covers client components, server components, and proper routing implementation.
Fix: Middleware not running in Next.js error
Quick fix for middleware not running in Next.js. Learn how to properly configure and troubleshoot Next.js middleware.