.png?table=block&id=3250c31d-b1e3-800f-baa8-d51b5653def5&cache=v2)
Do not index
Sometimes you want your blog to live at:
example.com/blogBut 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 blogVisitors 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:
- Your domain uses Cloudflare DNS
- Your website is live (example:
lovable.example.com)
- Your Feather blog URL is ready (example:
yourblog.feather.blog)
Step 1 — Create a Cloudflare Worker
Open your Cloudflare dashboard.
Go to:
Workers & PagesClick:
Create → Create WorkerGive it any name, for example:
site-routerStep 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.blogReplace 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/blogYour Feather blog should load.
Now open a blog post:
example.com/blog/my-first-postEverything should work normally.
What just happened
When someone visits:
example.com/blogCloudflare silently forwards the request to your Feather blog.
When someone visits:
example.comCloudflare 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.