How to add a WordPress Blog to a Next.js app as a subdirectory in the same domain to boost SEO

Hey there! lately I’ve been working on a project of mine which is made with Next.js.

However, for SEO/Marketing purposes one always has to add a blog to it.

Since I don’t like the idea of having to use a private CMS (Strapi/Contentful/etc…) as an API and having the sidetracking task of creating a full blown blog UI in Next.js, I tried to use WordPress as a blog.

There are maaany questions on the internet asking how it can be done, but very little info.
So here’s how I did it, the result will be something like this where

rusher.ai is a nextjs app and

https://rusher.ai/blog/guides/how-to-create-your-first-social-media-carousel-with-ai – is a sample wordpress blog article

You still get the amazing ability writing, previewing and publishing articles in wordpress, and you don’t get the SEO penalties of having them in different subdomains

Step 1: Host both things somewhere.

To get started both next.js and WordPress need to be publicly accessible.

In my case I chose to host the Next.js app at the top level domain rusher.ai, I the wordpress blog at the ‘blog’ subdomain. So if you check, https://blog.rusher.ai also works and it’s the “real” deployment.

Step 2: Add the rewrites in Next.js

The following piece of code that you add to next.config.js will make it so that any page that isn’t found by the Next.js app, is actually served from the WordPress blog. (Of course, remember changing rusher.ai with your actual domain)

// next.config.js

module.exports = {
  async rewrites() {
    return {
      fallback: [
        {
          source: "/:path*",
          destination: `https://blog.rusher.ai/:path*`,
        },
      ],
    }
  },
}

Step 3: Set Up WordPress to Use Your Root Domain

Let’s get WordPress to serve pages from your root domain by tweaking the wp-config.php file. Add these lines:

define('WP_SITEURL', 'https://blog.rusher.ai');
define('WP_HOME', 'https://rusher.ai');
define('COOKIE_DOMAIN', '.rusher.ai');
  • WP_SITEURL: This sets the subdomain as the base URL for WordPress assets and admin pages.
  • WP_HOME: This ensures that all generated links use the root domain.
  • COOKIE_DOMAIN: This shares cookies across the subdomains and root domain to maintain your login session.

Step 4: Tidying it all up

WordPress sometimes behaves unexpectedly, so we need to make a few adjustments in wp-content/themes/your-theme/functions.php.

First, stop WordPress from redirecting to its idea of the “correct” URL:

remove_filter('template_redirect','redirect_canonical');

This prevents WordPress from redirecting pages to the subdomain URL, which is not what we want.

Next, adjust the REST API base URL to use the subdomain:

add_filter('rest_url', 'serve_rest_url_on_wp_subdomain');
function serve_rest_url_on_wp_subdomain ($url) {
  return str_replace('https://rusher.ai', 'https://blog.rusher.ai', $url);
}

This change is crucial to avoid CORS errors when accessing the admin pages on the subdomain. You could refine this with a RegEx to only replace the start of the string and use the global variables for URLs instead of hardcoding them.

Lastly, if you’re using Yoast SEO, update the canonical URLs it generates:

add_filter( 'wpseo_canonical', 'yoast_seo_canonical_fix’ );
function yoast_seo_canonical_fix( $canonical_url ) {
  return str_replace('https://blog.', 'https://', untrailingslashit($canonical_url));
}

This does two things:

  1. Ensures canonical URLs use the root domain.
  2. Removes trailing slashes to match the final URL, which Next.js removes via redirects.

and TA DA !

If everything is working, you’re all set!

All credit goes to Tom Hicks who’s the original author and helped me figure this out!

Leave a Comment

Your email address will not be published. Required fields are marked *