Infrastructure22 min readFeatured

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.

By CyberClarencePublished March 12, 2026Updated March 15, 2026

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. 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. 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. 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. 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. 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 requests

The 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 deploy

Step 4: Configure Path Rules

The Worker route configuration tells Cloudflare which requests should be handled by your Worker. Here's the path mapping:

Path PatternDestinationHandler
/*WordPress origin serverCloudflare 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.com

Verification 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:

  1. 1
    Migrate your domain to Cloudflare free tier with zero downtime
  2. 2
    You invite our team to your Cloudflare account (read-only + Workers access)
  3. 3
    We configure the reverse proxy with custom Worker code
  4. 4
    Set up path rules: /* → WordPress, /blog → Framer
  5. 5
    SSL, caching, and security headers configured
  6. 6
    Full testing and verification
  7. 7
    Handoff 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.

Need Help Setting This Up?

Our team can handle the entire Cloudflare + Framer reverse proxy setup for you. Safe, fast, zero downtime.