I have a Next.js application hosted on Vercel at mydomain. My WordPress blog is installed on a DigitalOcean droplet at wp.example. My DNS is managed by Vercel, and I have successfully created an 'A' record for the 'wp' subdomain pointing to my DigitalOcean droplet's IP.
Goal:
I want to serve the WordPress blog under the /wp subdirectory of my main Next.js domain, so that blog posts are accessible at URLs like:
example/wp/blog-post-1
example/wp/blog-post-2
example/wp/blog-post-3
Current Setup: Next.js application: example (Vercel) WordPress blog: wp.example (DigitalOcean) DNS: Vercel
Attempts:
vercel.json Redirects: I initially tried using vercel.json redirects, but this resulted in the browser redirecting to wp.mydomain, which is not the desired behavior. next.config.js Rewrites (Preferred): I understand that using next.config.js rewrites in Next.js is the correct approach.
// v0-user-next.config.js
module.exports = {
rewrites: async () => {
return [
{
source: '/wp/:path*',
destination: '/:path*',
},
];
},
experimental: {
turbo: {
loaders: {
'.mdx': ['@mdx-js/loader', { providerImportSource: '@mdx-js/react' }],
},
},
},
};
Nginx Configuration: The wordpress installation is running on a digital ocean droplet. The following Nginx server block is used for the wordpress site. However, I think that the return 301 is causing issues.
server {
server_name wp.example;
root /var/www/wp.example;
index index.php index.html index.htm;
# WordPress permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP-FPM configuration (adjust based on version)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Allow access to static files in wp-includes, wp-admin, wp-content
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|otf|eot|mp4|webm|ogg|mp3|wav|zip|tar|gz|bz2|7z|rar|xml|json)$ {
allow all;
expires max;
log_not_found off;
}
# Disable .htaccess and other hidden files
location ~ /\. {
deny all;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/wp.mydomain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/wp.mydomain/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
add_header Strict-Transport-Security "max-age=31536000" always; # managed by Certbot
ssl_trusted_certificate /etc/letsencrypt/live/wp.mydomain/chain.pem; # managed by Certbot
ssl_stapling on; # managed by Certbot
ssl_stapling_verify on; # managed by Certbot
return 301 $request_uri;
}
server {
if ($host = wp.example) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name wp.example;
root /var/www/wp.example;
index index.php index.html index.htm;
# WordPress permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP-FPM configuration (adjust based on version)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Disable .htaccess and other hidden files
location ~ /.(?!well-known).* {
deny all;
}
}