Use Subfolders With Any Damn Site When You Are on Cloudflare DNS

Want your blog to live at example.com/blog? If your domain uses Cloudflare DNS, you can route the /blog subfolder to your Feather blog using a simple Cloudflare Worker. This guide shows you exactly how to set it up in a few minutes.

Published on:

Use Subfolders With Any Damn Site When You Are on Cloudflare DNS
Do not index
Sometimes you want your blog to live at:
example.com/blog
But your website is hosted somewhere else.
Example:
  • Your main website → hosted on Webflow / Lovable / Framer / custom server
  • Your blog → hosted on Feather
Most hosting providers do not allow this, because they expect to control the entire domain.
If your domain uses Cloudflare DNS, you can easily make this work.
This guide will show you how.

What we are going to do

We will route traffic like this:
example.com        → your main website
example.com/blog   → your Feather blog
Visitors will stay on your domain. They will never see the Feather domain.
Behind the scenes, Cloudflare simply forwards the request to the correct app.

What you need

Before starting, make sure:
  1. Your domain uses Cloudflare DNS
  1. Your website is live (example: lovable.example.com)
  1. Your Feather blog URL is ready (example: yourblog.feather.blog)

Step 1 — Create a Cloudflare Worker

Open your Cloudflare dashboard.
Go to:
Workers & Pages
Click:
Create → Create Worker
Give it any name, for example:
site-router

Step 2 — Add the routing code

Replace the default Worker code with this:
const APEX_DOMAIN = "example.com"
const MAIN_ORIGIN = "lovable.example.com"

const ROUTES = [
  {
    paths: ["/blog", "/_feather"],
    origin: "yourblog.feather.blog",
    stripPrefix: false,
  },
]

export default {
  async fetch(request) {
    const url = new URL(request.url)

    // Redirect www → apex
    if (url.hostname === `www.${APEX_DOMAIN}`) {
      url.hostname = APEX_DOMAIN
      return Response.redirect(url.toString(), 301)
    }

    // Normalize trailing slash
    if (url.pathname.endsWith("/") && url.pathname !== "/") {
      url.pathname = url.pathname.slice(0, -1)
      return Response.redirect(url.toString(), 301)
    }

    const route = matchRoute(url.pathname)

    if (route) {
      return proxy(request, url, route.origin, route)
    }

    return proxy(request, url, MAIN_ORIGIN)
  },
}

function matchRoute(pathname) {
  for (const route of ROUTES) {
    for (const basePath of route.paths) {
      if (
        pathname === basePath ||
        pathname.startsWith(basePath + "/")
      ) {
        return { ...route, basePath }
      }
    }
  }
  return null
}

async function proxy(request, url, origin, route = null) {
  const upstream = new URL(url)

  upstream.hostname = origin

  if (route?.stripPrefix) {
    upstream.pathname =
      upstream.pathname.replace(route.basePath, "") || "/"
  }

  const proxyRequest = new Request(upstream.toString(), request)

  proxyRequest.headers.set("X-Forwarded-Host", url.host)

  return fetch(proxyRequest)
}
Now update these values:
example.com
lovable.example.com
yourblog.feather.blog
Replace them with:
  • your actual domain
  • the domain where your main website is hosted
  • your Feather blog URL

Step 3 — Attach the Worker to your domain

Inside the Worker settings, add a route:
example.com/*
This tells Cloudflare:
Run this Worker for every request on this domain.

Step 4 — Test your blog

Visit:
example.com/blog
Your Feather blog should load.
Now open a blog post:
example.com/blog/my-first-post
Everything should work normally.

What just happened

When someone visits:
example.com/blog
Cloudflare silently forwards the request to your Feather blog.
When someone visits:
example.com
Cloudflare sends them to your main website.
Your visitors only see your domain.

Need help?

If you run into any issues setting this up, reach out to us at support@feather.so and we’ll help you get it working.