Framer Reverse Proxy: Host Your Blog on a Custom Domain with Cloudflare
The complete guide to running your WordPress site on /* and your Framer blog on /blog/* using Cloudflare's free tier. Zero downtime, full SEO control, one domain.
Table of Contents
What Is a Framer Reverse Proxy?
A reverse proxy sits between your visitors and your origin servers, routing requests to different backends based on the URL path. In this setup, visitors see a single domain (e.g., yourdomain.com) but different paths are served by different platforms.
The Goal:
yourdomain.com/* → WordPress (your main site)
yourdomain.com/blog/* → Framer (your blog on customer42.framer.site)
This means your visitors never see the .framer.site subdomain. Google indexes everything under your main domain, giving you consolidated SEO authority. And the best part? This entire setup runs on Cloudflare's free tier.
Why Cloudflare? (And Why Free Tier Is Enough)
Cloudflare is the ideal platform for this setup because of its global edge network, Workers runtime, and generous free tier.
Free DNS
Cloudflare provides free DNS management with global Anycast. Your domain resolves in under 20ms from anywhere in the world.
Free SSL
Automatic SSL certificates for your domain. No manual certificate management, no renewal headaches.
Free Workers
100,000 requests/day on the free plan. More than enough for most blogs. Workers run at the edge, adding near-zero latency.
Other solutions like Nginx, Caddy, or AWS CloudFront can achieve similar results, but they require server management, SSL configuration, and ongoing maintenance. Cloudflare handles all of this for free.
The Architecture: WordPress + Framer on One Domain
Here's how the traffic flows in this setup:
┌──────────────────────────────────────────────────┐
│ Visitor │
│ https://yourdomain.com/blog/post-1 │
└──────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ Cloudflare Edge Network │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Cloudflare Worker │ │
│ │ │ │
│ │ if (path starts with "/blog") │ │
│ │ → proxy to customer42.framer.site │ │
│ │ else │ │
│ │ → proxy to WordPress origin │ │
│ └─────────────────────────────────────────────┘ │
└──────────┬────────────────────┬──────────────────┘
│ │
┌─────▼─────┐ ┌──────▼──────┐
│ WordPress │ │ Framer │
│ Server │ │ Sites │
│ (origin) │ │ .framer.site│
└───────────┘ └─────────────┘Step 1: Migrate Your Domain to Cloudflare (Zero Downtime)
The easiest and safest approach is to first migrate your domain's DNS to Cloudflare. This can be done with absolutely zero downtime if you follow these steps carefully.
Migration Process
- 1
Sign up for Cloudflare (Free)
Go to cloudflare.com and create a free account. Click "Add a Site" and enter your domain name. Select the Free plan.
- 2
Cloudflare scans your existing DNS records
Cloudflare automatically imports all your existing DNS records (A, CNAME, MX, TXT, etc.). Verify every record matches your current registrar's DNS settings. This is critical for zero downtime.
- 3
Update nameservers at your registrar
Cloudflare gives you two nameservers (e.g., ada.ns.cloudflare.com, bob.ns.cloudflare.com). Log into your domain registrar (GoDaddy, Namecheap, Google Domains, etc.) and replace the existing nameservers with Cloudflare's.
- 4
Wait for propagation (2-24 hours)
DNS propagation typically takes 2-24 hours. During this time, your site continues working normally because Cloudflare already has all your DNS records configured identically.
- 5
Verify activation
Cloudflare will email you once your domain is active. You can also check in the Cloudflare dashboard — the status will change from "Pending" to "Active".
Why zero downtime? Because Cloudflare imports all your existing DNS records before you switch nameservers. From the moment the nameserver change propagates, Cloudflare serves the exact same DNS records your previous provider was serving. Visitors never notice a thing.
Step 2: Configure DNS Records
Once your domain is active on Cloudflare, verify your DNS records:
# Your existing WordPress DNS records should look like:
Type Name Content Proxy
───── ─────────────── ────────────────── ──────
A yourdomain.com 203.0.113.50 Proxied ☁️
CNAME www yourdomain.com Proxied ☁️
MX yourdomain.com mail.yourdomain.com DNS only
# Make sure the A record and www CNAME
# are set to "Proxied" (orange cloud icon)
# This is required for the Worker to intercept requestsThe key detail is that your main domain's A record (or CNAME) must be proxied through Cloudflare (orange cloud icon enabled). DNS-only records bypass the Cloudflare edge and won't trigger your Worker.
Step 3: Set Up Cloudflare Workers for Reverse Proxy
Cloudflare Workers are serverless functions that run at Cloudflare's edge. We'll use a Worker to route /blog/* requests to Framer while letting everything else pass through to WordPress.
Cloudflare Worker — framer-reverse-proxy.js
// Cloudflare Worker: Framer Reverse Proxy
// Routes /blog/* to your Framer site
const FRAMER_SITE = "customer42.framer.site";
const BLOG_PREFIX = "/blog";
export default {
async fetch(request) {
const url = new URL(request.url);
// Only intercept /blog paths
if (!url.pathname.startsWith(BLOG_PREFIX)) {
// Let everything else pass through to origin (WordPress)
return fetch(request);
}
// Construct the Framer URL
// /blog/my-post → customer42.framer.site/blog/my-post
const framerUrl = new URL(url.pathname + url.search,
"https://" + FRAMER_SITE
);
// Fetch from Framer with modified headers
const framerResponse = await fetch(framerUrl.toString(), {
method: request.method,
headers: {
...Object.fromEntries(request.headers),
"Host": FRAMER_SITE,
"X-Forwarded-Host": url.hostname,
"X-Forwarded-Proto": "https",
},
redirect: "manual",
});
// Create response with modified headers
const response = new Response(framerResponse.body, {
status: framerResponse.status,
statusText: framerResponse.statusText,
headers: framerResponse.headers,
});
// Rewrite any Framer URLs in the response
// to use your domain instead
const contentType = response.headers.get("content-type") || "";
if (contentType.includes("text/html")) {
let html = await response.text();
// Replace Framer site references with your domain
html = html.replaceAll(
FRAMER_SITE,
url.hostname
);
return new Response(html, {
status: response.status,
headers: {
...Object.fromEntries(response.headers),
"Content-Type": "text/html; charset=utf-8",
// Add security headers
"X-Frame-Options": "SAMEORIGIN",
"X-Content-Type-Options": "nosniff",
},
});
}
return response;
},
};Deploying the Worker
# Install Wrangler CLI
npm install -g wrangler
# Login to Cloudflare
wrangler login
# Create wrangler.toml
cat > wrangler.toml << 'EOF'
name = "framer-reverse-proxy"
main = "src/index.js"
compatibility_date = "2026-03-01"
[triggers]
routes = [
{ pattern = "yourdomain.com/blog/*", zone_name = "yourdomain.com" }
]
EOF
# Deploy
wrangler deployStep 4: Configure Path Rules
The Worker route configuration tells Cloudflare which requests should be handled by your Worker. Here's the path mapping:
| Path Pattern | Destination | Handler |
|---|---|---|
/* | WordPress origin server | Cloudflare passthrough (default) |
/blog/* | customer42.framer.site/blog/* | Cloudflare Worker |
Important: Make sure your Framer site's pages are structured under /blog. In Framer, create a folder called "blog" and put your pages inside it. This ensures the URL paths match between your domain and the Framer site.
Step 5: SSL/TLS and Caching Configuration
Proper SSL and caching configuration ensures security and performance.
SSL/TLS Settings
- Go to SSL/TLS → Overview in your Cloudflare dashboard
- Set encryption mode to "Full (strict)" if your WordPress server has a valid SSL certificate
- If WordPress uses a self-signed cert, use "Full" mode instead
- Enable "Always Use HTTPS" under SSL/TLS → Edge Certificates
- Enable "Automatic HTTPS Rewrites" to fix mixed content
Cache Configuration
// Add caching to your Worker for better performance
const CACHE_TTL = 3600; // 1 hour
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (!url.pathname.startsWith("/blog")) {
return fetch(request);
}
// Check cache first
const cache = caches.default;
const cacheKey = new Request(url.toString(), request);
let response = await cache.match(cacheKey);
if (response) {
return response; // Cache hit
}
// Cache miss — fetch from Framer
response = await fetchFromFramer(request, url);
// Cache the response
response = new Response(response.body, response);
response.headers.set("Cache-Control",
"public, max-age=" + CACHE_TTL
);
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
},
};Step 6: Testing and Verification
After deployment, verify everything works correctly:
# Test WordPress (should return your WordPress site)
curl -I https://yourdomain.com/
# Expected: HTTP/2 200, WordPress headers
# Test Framer blog (should return Framer content)
curl -I https://yourdomain.com/blog/
# Expected: HTTP/2 200, Framer content
# Test a specific blog post
curl -I https://yourdomain.com/blog/my-first-post
# Expected: HTTP/2 200
# Verify no Framer branding leaks
curl -s https://yourdomain.com/blog/ | grep "framer.site"
# Expected: No output (all references rewritten)
# Test SSL
curl -vI https://yourdomain.com/blog/ 2>&1 | grep "SSL certificate"
# Expected: Valid SSL for yourdomain.comVerification Checklist
- Homepage (/) loads WordPress normally
- /blog/ loads your Framer blog content
- All blog post links work (/blog/post-slug)
- Images and assets load correctly
- No .framer.site URLs visible in page source
- SSL certificate is valid for your domain
- Google Search Console can crawl /blog/ pages
- Internal links in blog posts point to yourdomain.com/blog/...
SEO Benefits of This Setup
Hosting your Framer blog on a subdirectory (/blog) rather than a subdomain (blog.yourdomain.com) has significant SEO advantages:
Subdomain (Worse for SEO)
- Google treats subdomains as separate sites
- Domain authority is not shared
- Backlinks to blog don't boost main site
- Requires separate Search Console property
Subdirectory (Better for SEO)
- Google treats /blog as part of your main site
- Full domain authority passes to blog content
- Blog backlinks boost entire domain
- Single Search Console property for everything
Real-world impact: Studies show that subdirectory blogs receive up to 50% more organic traffic than equivalent subdomain blogs, primarily because domain authority flows directly to the blog content. Companies like HubSpot, Shopify, and Buffer all use subdirectory blogs for this reason.
Common Issues & Troubleshooting
Blog pages return 404
Ensure your Framer site has pages under the /blog path. In Framer, create a "blog" folder and structure your pages inside it. The URL paths must match between your domain and the Framer site.
Images/assets not loading
Framer may serve assets from CDN URLs. Update your Worker to also proxy asset requests, or configure Framer to use relative paths.
Mixed content warnings
Enable "Automatic HTTPS Rewrites" in Cloudflare SSL/TLS settings. This converts any http:// references to https:// automatically.
Redirect loops
Set your SSL mode to "Full" or "Full (strict)" instead of "Flexible". Flexible mode can cause redirect loops with servers that force HTTPS.
Slow initial load after cache expires
Increase CACHE_TTL in your Worker, or use Cloudflare's Always Online feature. Consider implementing stale-while-revalidate caching.
Framer analytics not working
Framer's built-in analytics may not work through the proxy. Use a universal analytics solution like PostHog, Plausible, or Google Analytics instead.
Advanced: Multiple Framer Sections
You can extend this pattern to proxy multiple paths to different Framer sites or other platforms:
// Advanced: Multiple proxy targets
const ROUTES = {
"/blog": "customer42.framer.site",
"/help": "help-center.framer.site",
"/changelog": "updates.framer.site",
};
export default {
async fetch(request) {
const url = new URL(request.url);
// Find matching route
for (const [prefix, target] of Object.entries(ROUTES)) {
if (url.pathname.startsWith(prefix)) {
return proxyToTarget(request, url, target);
}
}
// Default: pass through to origin
return fetch(request);
},
};
async function proxyToTarget(request, url, targetHost) {
const targetUrl = new URL(
url.pathname + url.search,
"https://" + targetHost
);
const response = await fetch(targetUrl.toString(), {
method: request.method,
headers: {
...Object.fromEntries(request.headers),
Host: targetHost,
"X-Forwarded-Host": url.hostname,
},
redirect: "manual",
});
// Rewrite target host references in HTML
const contentType = response.headers.get("content-type") || "";
if (contentType.includes("text/html")) {
let html = await response.text();
html = html.replaceAll(targetHost, url.hostname);
return new Response(html, {
status: response.status,
headers: response.headers,
});
}
return response;
}Done-For-You Service
Don't want to handle the technical setup yourself? We offer a fully managed reverse proxy setup service.
We'll Set It Up For You
The easiest, safest, and fastest way to get your Framer blog running on your custom domain.
Here's exactly what we do:
- 1Migrate your domain to Cloudflare free tier with zero downtime
- 2You invite our team to your Cloudflare account (read-only + Workers access)
- 3We configure the reverse proxy with custom Worker code
- 4Set up path rules: /* → WordPress, /blog → Framer
- 5SSL, caching, and security headers configured
- 6Full testing and verification
- 7Handoff with documentation
One-time setup fee
2,500€
Handled safely and quickly from your Cloudflare account
We typically complete the setup within 24-48 hours
Frequently Asked Questions
Can I use Framer for my blog on a custom domain?
Yes. Using a Cloudflare Worker as a reverse proxy, you can serve your Framer blog on any path (like /blog) of your custom domain. Visitors will never see the .framer.site URL.
Is a Cloudflare reverse proxy free?
Cloudflare's free plan includes DNS, SSL, and 100,000 Worker requests per day — more than enough for most blogs. You only pay if you exceed the free tier limits.
Will there be downtime during the domain migration?
No. Cloudflare imports all your existing DNS records before you switch nameservers. The transition is seamless with zero downtime when done correctly.
Is /blog better than blog.yourdomain.com for SEO?
Yes. Google treats subdirectories as part of the main domain, so domain authority flows to your blog content. Subdomains are treated as separate sites, splitting your SEO equity.
Can I reverse proxy other platforms besides Framer?
Yes. The same Cloudflare Worker pattern works for any platform — Webflow, Ghost, Notion, or any other site. You can proxy multiple paths to different origins.
What happens if Cloudflare goes down?
Cloudflare has 99.99% uptime SLA and operates across 300+ data centers globally. Downtime is extremely rare. If needed, you can temporarily point your DNS directly to your origins.
Can I use this with Shopify instead of WordPress?
Absolutely. The reverse proxy pattern works with any origin server. Replace the WordPress origin with your Shopify store, and the Worker handles the routing identically.
How do I update my Framer blog content?
Just edit your site in Framer and publish as usual. The reverse proxy fetches content from your Framer site in real-time (or from cache). No deployment or configuration changes needed.
Conclusion
Setting up a Framer reverse proxy with Cloudflare is one of the smartest infrastructure decisions you can make for your web presence. You get the visual design power of Framer for your blog, the full-featured backend of WordPress for your main site, and consolidated SEO authority under a single domain.
The entire setup runs on Cloudflare's free tier, takes about an hour to configure if you're technical, and requires zero ongoing maintenance.
Whether you DIY it with this guide or use our done-for-you service, the result is the same: a professional, SEO-optimized setup that gives you the best of both worlds.