This is a Next.js project bootstrapped with create-next-app.
If you're experiencing favicon 404 errors on VPS but not on Vercel, follow these steps:
Ensure your web server (Nginx/Apache) serves static files from the public directory:
Nginx Configuration:
server {
listen 443 ssl;
server_name yourdomain.com;
# SSL configuration
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
location / {
proxy_pass http://localhost:3000;
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;
}
# Serve static files directly
location ~* \.(ico|css|js|gif|jpe?g|png|svg|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri @proxy;
}
location @proxy {
proxy_pass http://localhost:3000;
}
# Specific favicon handling
location = /favicon.ico {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri @proxy;
}
}Apache Configuration (.htaccess):
# Enable static file serving
<FilesMatch "\.(ico|css|js|gif|jpe?g|png|svg|woff2?)$">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header set Cache-Control "public, immutable"
</FilesMatch>
# Specific favicon handling
<Files "favicon.ico">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header set Cache-Control "public, immutable"
</Files>-
Verify build output:
npm run build # Check that favicon.ico exists in .next/static/ or public/ -
Ensure proper file permissions:
chmod 644 public/favicon.ico chmod 755 public/
-
Test static file serving:
curl -I https://yourdomain.com/favicon.ico # Should return 200, not 404
- Missing public directory mapping: Ensure your process manager (PM2, systemd) serves from correct directory
- Incorrect base path: Check if your app is deployed in a subdirectory
- File permissions: Ensure web server can read the favicon file
- CDN/Proxy issues: Clear CDN cache or check proxy configuration
- HTTPS redirect loops: Ensure proper SSL termination
# Check if file exists
ls -la public/favicon.ico
# Test direct file access
curl -v https://yourdomain.com/favicon.ico
# Check Next.js logs
npm run start
# Look for static file serving errors
# Verify build output
find .next -name "favicon.ico" -o -name "*favicon*"If issues persist, try these alternatives:
-
Use absolute URLs in metadata:
// In layout.tsx export const metadata = { icons: { icon: 'https://yourdomain.com/favicon.ico', }, }
-
Add explicit route handler:
// app/favicon.ico/route.ts import { NextRequest } from 'next/server' import fs from 'fs' import path from 'path' export async function GET(request: NextRequest) { const filePath = path.join(process.cwd(), 'public', 'favicon.ico') const fileBuffer = fs.readFileSync(filePath) return new Response(fileBuffer, { headers: { 'Content-Type': 'image/x-icon', 'Cache-Control': 'public, max-age=31536000, immutable', }, }) }
The key difference between Vercel and VPS is that Vercel automatically handles static file serving optimally, while VPS requires manual server configuration.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.