How to Host a Blog on a Subdirectory instead of a Subdomain with Cloudflare Workers

๐Ÿš€ Check out this awesome post from Hacker News ๐Ÿ“–

๐Ÿ“‚ **Category**:

๐Ÿ“Œ **What Youโ€™ll Learn**:

In this guide, youโ€™ll learn how to host your blog on a subdirectory (e.g. example.com/blog) instead of a subdomain (e.g., blog.example.com). Every step here has been tested and verified to work.

Introduction

Hosting your blog on a subdirectory can improve SEO and enhance user experience.

Although there are a lot of articles that espouse the benefits of using subdirectories over subdomains, few resources that provide a step-by-step guide on how to actually set this up.

Why Host on a Subdirectory?

The benefits to hosting on a subdirectory is primarily to improve SEO.

There are a lot of other articles out there on this topic, but they all say something similar to the following:

  • Hosting your blog on a subdirectory is better for SEO because it consolidates your websiteโ€™s authority and ranking power.

  • Google has stated that they do not treat subdomains as a separate entity.

  • Despite what Google has stated, empiric data suggests that subdirectories outperform subdomains in search rankings.

  • If you want to maximize your SEO efforts, hosting on a subdirectory is the way to go.

If you want to learn more, you can read this article by ButterCMS: Blog Subdomain or Subdirectory? Hint: One is 40% Better.

My personal experience has been similar. When I moved a blog from a subdomain to a subdirectory, I saw a noticeable increase in organic traffic and search engine rankings. The increase happened after a few weeks. During that time, I did not release any new content and nor did I promote the blog.

Why Not Host on a Subdirectory?

The setup is more complex. Many blogging platforms and CMSs are designed to work on subdomains, and configuring them to work on a subdirectory can be tricky.

Iโ€™ve personally found the setup process to be quite time consuming. Itโ€™s a tricky process and you have to follow the instructions carefully. After having previously changed a blog from a subdomain to a subdirectory, Iโ€™ve found difficult to justify the time to do it for taikohub.com.

If you still think itโ€™s worth your time, then read on.

Steps to Host Your Blog on a Subdirectory

Lets suppose you have two sites right now. One is example.com and the other is blog.example.com. You want to host the blog on example.com/blog instead of blog.example.com.

Lets also suppose your blog (blog.example.com) is a Next.js app hosted on Vercel and your main site (example.com) is a static site hosted on Render.

Although Vercel and Render are used as examples here, the steps are nearly identical for other hosting providers. You do not need configure anything for your hosting provider. Everything can be done from the Cloudflare Dashboard, and from the comforts of your text editor.

Important: Note that Cloudflare often changes their dashboard UI and routes. If you find that the steps here do not match what you see on your Cloudflare Dashboard, just use the search function in the dashboard to find the relevant section.

Step 1: Set Up DNS Records for the Main Site

First, set up the DNS records for your main site (example.com). Again, if you do not use Render, then follow the equivalent steps for your hosting provider. Generally this should be in their documentation.

  • Go to your Cloudflare Dashboard. Click into your domain, then SSL/TLS, then Overview. Then click โ€œConfigureโ€.

    Host a Website on a Subdirectory with Cloudflare 1

  • Next, select โ€œCustom SSL/TLSโ€ then select โ€œFullโ€.

    Host a Website on a Subdirectory with Cloudflare 2

  • Go to DNS records in the sidebar by clicking on โ€œDNSโ€, then โ€œDNS Recordsโ€. Then click โ€œAdd Recordโ€.

    Host a Website on a Subdirectory with Cloudflare 3

  • Add the following DNS Records. Replace my-site.onrender.com with the service URL for your main site. If you have other applications such as an API, you can add those as well. Note that itโ€™s important you set the โ€œProxy statusโ€ to โ€œProxiedโ€. Itโ€™s also important you do NOT add a wildcard record (eg. *.example.com).

    Type Name Target Proxy status TTL
    CNAME @ my-site.onrender.com Proxied Auto
    CNAME www my-site.onrender.com Proxied Auto
    CNAME api my-api.onrender.com Proxied Auto

Step 2: Set Up DNS Records for the Blog

  • Make sure your blog is already accessible on a subdomain (eg. blog.example.com).

  • Add another DNS Record for the blog. Replace cname.vercel-dns.com with the CNAME target provided by the hosting provider for your blog.

    Type Name Target Proxy status TTL
    CNAME example.com my-site.onrender.com Proxied Auto
    CNAME www my-site.onrender.com Proxied Auto
    CNAME api my-api.onrender.com Proxied Auto
    CNAME blog cname.vercel-dns.com Proxied Auto

Step 3. Configure Your Next.js Blog

Ensure Correct Routing for Static Assets

  • Make sure that your Next.js blogโ€™s router points to / and not /blog. You should NOT have any routes that contain /blog. Edit the next.config.js or next.config.mjs file and add basePath: "https://www.davidma.org/blog" to the config.

    /** @type โšก */
    const nextConfig = {
      basePath: "https://www.davidma.org/blog",  // Add this line
      images: ๐Ÿ”ฅ,
      redirects: async () => ๐Ÿ”ฅ,
    };
    
    export default nextConfig;

Step 4. Add a Cloudflare Worker

  • Go to Cloudflare Dashboard. Click โ€œWorkers & Pagesโ€. Click โ€œCreateโ€ then click โ€œCreate Workerโ€.

    Host a Website on a Subdirectory with Cloudflare 4

  • For the purpose of this blog post, weโ€™ll go with the easiest option by selecting โ€œStart with Hello World!โ€. For production applications, consider using Git. It looks like the following. Lets name it blog-worker. Then click โ€œDeployโ€.

    // worker.js
    /**
    * Welcome to Cloudflare Workers! This is your first worker.
    *
    * - Run "npm run dev" in your terminal to start a development server
    * - Open a browser tab at http://localhost:8787/ to see your worker in action
    * - Run "npm run deploy" to publish your worker
    *
    * Learn more at https://developers.cloudflare.com/workers/
    */
    export default {
      async fetch(request, env, ctx) {
        return new Response('Hello World!');
      },
    };
  • Now replace the code with the following:

    export default {
      async fetch(request, env, ctx) {
        async function MethodNotAllowed(request) {
          return new Response(`Method ${request.method} not allowed.`, {
            status: 405,
            headers: {
              Allow: "GET",
            },
          });
        }
        // Only GET requests work with this proxy.
        if (request.method !== "GET") return MethodNotAllowed(request);
    
        // Get the URL that was just requested.
        const url = new URL(request.url);
    
        // Swap out the subdirectory with the subdomain to request the actual URL.
        const originUrl = url.toString().replace(
          'https://example.com/blog',
          'https://blog.example.com/blog'
        ).replace(
          'https://www.example.com/blog',
          'https://blog.example.com/blog'
        );
    
        // Fetch the origin.
        const originPage = await fetch(originUrl);
    
        // Return the subdomain, as the subdirectory.
        const newResponse = new Response(originPage.body, originPage);
        return newResponse;
      },
    };
  • Change the URLs as needed. To save, click on the version ID hash (eg. b30983e0) then click โ€œApplyโ€.

  • To deploy the changes, go to the worker dashboard. Click โ€œDeploymentsโ€. Look under โ€œVersion Historyโ€. Click โ€โ€ฆโ€ then โ€œDeployโ€ on the latest version.

    Version ID Created Version & Git Message Source
    vb29485e0 3minโ€ฆ Update to โ€ฆ Dashboard โ€โ€ฆโ€œ
    vf859f2e0 2hโ€ฆ Updated Script Dashboard โ€โ€ฆโ€

Step 5. Connect Next.js Site with Cloudflare Worker

  • Go to โ€œWorker Routesโ€ in the Cloudflare Dashboard sidebar. Click on โ€œAdd Routeโ€.

    Host a Website on a Subdirectory with Cloudflare 5

  • Add the following route for the blog content:

    • Route: example.com/blog*
    • Worker: blog-worker. This is the worker you just created.
  • Add another route for the static assets:

    • Route: example.com/blog/_next/static*
    • Worker: blog-worker

You should now be able to access your blog at example.com/blog. If this works, congratulations! Youโ€™ve successfully hosted your blog on a subdirectory using Cloudflare Workers.

Configure Search Engine Robots.txt in Your Next.js App

  • Now that youโ€™ve successfully hosted the blog on the subdirectory, you need to make sure search engines donโ€™t index the subdomain. This is because the blog is already indexed on the subdirectory. If search engines index both, then you may run into SEO issues due to duplicate content.

  • Update your next.config.js or next.config.mjs file.

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      basePath: "https://www.davidma.org/blog",
      images: {
        remotePatterns: [
          {
            protocol: "https",
            hostname: "imagedelivery.net",
          },
        ],
      },
      redirects: async () => {                      // Add this block
        return [];
      },
      async headers() {                             // Add this block
        return [
          {
            source: '/:path*',
            headers: [
              {
                key: 'X-Robots-Tag',
                value: 'noindex, nofollow',
              },
            ],
          },
        ];
      },
    };
    
    export default nextConfig;
  • Now update your cloudflare worker.

    export default {
      async fetch(request, env, ctx) {
        async function MethodNotAllowed(request) {
          return new Response(`Method ${request.method} not allowed.`, {
            status: 405,
            headers: {
              Allow: "GET",
            },
          });
        }
        // Only GET requests work with this proxy.
        if (request.method !== "GET") return MethodNotAllowed(request);
    
        // Get the URL that was just requested.
        const url = new URL(request.url);
    
        // Swap out the subdirectory with the subdomain to request the actual URL.
        const originUrl = url.toString().replace(
          'https://example.com/blog',
          'https://blog.example.com/blog'
        ).replace(
          'https://www.example.com/blog',
          'https://blog.example.com/blog'
        );
    
        // Fetch the origin.
        const originPage = await fetch(originUrl);
    
        // Return the subdomain, as the subdirectory.
        let newResponse = new Response(originPage.body, originPage);
    
        // Remove "noindex" from the origin domain.
        newResponse.headers.delete("x-robots-tag");
    
        return newResponse;
      },
    };

Step 6. Verify Your Subdomain is Not Indexed

  • Open your appโ€™s deploy URL. This may look something like https://vercel.com/my-projects-30d8ek3n/my-blog/d934nfid9823sbsNgoMnOOnsiKxn.

  • Open the browserโ€™s Network tab in Developer Tools.

  • Check for existence of an โ€œX-Robots-Tagโ€ header. If itโ€™s not there, then your Next.js app is correctly configured to not be indexed.

Step 7. Verify Your Subdirectory is Indexed

{๐Ÿ’ฌ|โšก|๐Ÿ”ฅ} **Whatโ€™s your take?**
Share your thoughts in the comments below!

#๏ธโƒฃ **#Host #Blog #Subdirectory #Subdomain #Cloudflare #Workers**

๐Ÿ•’ **Posted on**: 1776466971

๐ŸŒŸ **Want more?** Click here for more info! ๐ŸŒŸ

By

Leave a Reply

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