Blog Post

Webflow Reverse Proxy: The Complete Guide to Subdirectories, Multiple Domains and Staged Migrations

Webflow Reverse Proxy: The Complete Guide to Subdirectories, Multiple Domains and Staged Migrations

Last updated 25 September 2026. First published 18 September 2026.

A Webflow reverse proxy lets you serve a Webflow site, or part of one, under a URL that Webflow does not host directly. The three cases we get asked about are a Webflow blog at example.com/blog while the main site or app runs on Next.js, a docs or help centre at example.com/docs under a Webflow marketing site, and several business-line domains served from one Webflow project. Webflow supports all three on any paid Site plan, but it treats the proxy as your infrastructure. Webflow documents the settings; you build and maintain the routing layer, and Webflow Support will not debug it.

That split is where setups go wrong. The proxy usually works on day one. The problems show up weeks later: duplicate pages indexed on the origin subdomain, a sitemap listing the wrong hostnames, redirects that leak the origin, a cache that serves stale pages for hours after a publish, or a checkout that silently rejects every order. This guide is written for the team that has to own the proxy after launch. It covers the decision, every setup path we have seen work (Next.js rewrites, Cloudflare Workers, Webflow Cloud, NGINX, CloudFront and managed tools), the Webflow settings, production-grade code, what breaks behind a proxy, caching, sitemaps, localization, staged migrations, performance, cost and the checks to run before and after launch. Skywwward built the multi-domain, trilingual version of this for Hoovest, a Canadian financial group, and the SEO settings mattered as much as the routing.

What a Reverse Proxy Does in a Webflow Setup

A reverse proxy sits between the visitor and one or more origin servers. The visitor requests example.com/blog/post, the proxy fetches the page from where it actually lives, and returns it under the public URL. The visitor and search engines only ever see example.com.

In a Webflow context, the proxy runs in one of four directions:

Direction Public URL What the proxy does Typical reason
Webflow behind another site example.com/blog Forwards /blog/* to a Webflow origin subdomain Main site is a Next.js app or another platform, marketing wants Webflow for content
Other content behind a Webflow site example.com/docs Forwards /docs/* to a docs tool, help centre or app Main site is on Webflow, docs or product pages live elsewhere
One Webflow project, several domains brand-a.com, brand-b.com Maps each hostname to a section of one Webflow project Several business lines, one design system and CMS
Several Webflow sites, one domain example.com/, example.com/careers Routes paths to different Webflow projects Separate teams or workspaces own different sections

The reason teams want this instead of blog.example.com is consolidation: one domain in analytics, one backlink profile, one brand in search results. Google has said for years that it handles subdomains and subdirectories, so a proxy is not a ranking trick. What a subdirectory does give you is one place for internal linking, one sitemap, one Search Console property and one set of reports. For a marketing team that is worth a moving part. For a two-page site it is not.

When a Reverse Proxy Is the Right Call (and When It Is Not)

A reverse proxy adds infrastructure you have to own. It is worth it when the URL structure has a business reason behind it.

Good reasons:

  • The product app or docs already live on the main domain and marketing wants Webflow for everything else.
  • You are moving a blog from WordPress to Webflow but the rest of the site is not moving yet, and you want to migrate section by section.
  • You run several brands or business lines that need separate domains but should share one design system and CMS.
  • Legal or IT requires every request to pass through your own CDN, WAF or logging.

Reasons to skip it:

  • The whole site could move to Webflow. A full migration is less work over time than a permanent proxy.
  • You sell through Webflow Ecommerce or run Webflow Memberships on the pages you want to proxy. Both break behind a proxy (see the compatibility table below).
  • Nobody on the team can maintain Cloudflare, Vercel, NGINX or AWS configuration. When the proxy breaks, the site breaks, and Webflow Support will point you back at the proxy.
  • The “other” content is a Next.js or Astro app and your root site is Webflow. Webflow Cloud can mount it under your Webflow site without a hand-built proxy.

Use this to pick a path:

Your root site runs on You want Recommended path Effort
Next.js on Vercel Webflow blog or marketing pages under a path Next.js rewrites Low
Any app on Vercel (not Next.js) Same vercel.json rewrites Low
Webflow A Next.js or Astro app under a path Webflow Cloud Low
Webflow A third-party tool (help desk, docs) under a path Webflow Cloud proxy example or Cloudflare Worker Low to medium
Anything, domain on Cloudflare Path routing, multi-domain routing, header or HTML rewriting Cloudflare Worker Medium
Your own servers Full control, on-prem policy NGINX Medium
AWS-standardised company Path routing inside an existing distribution CloudFront Medium
No engineers Several Webflow sites on one domain Subfold or similar managed tool Low, monthly fee
Enterprise Webflow contract Direct Webflow involvement Ask Webflow Sales High

Webflow Settings You Need Before Any Proxy Works

Every path below depends on the same Webflow configuration. These come from Webflow’s reverse proxy documentation. Skipping any of them is the most common cause of SEO problems later.

  1. Use a paid Site plan with a custom domain. Proxying *.webflow.io staging domains is against Webflow’s Terms of Service, and several features only work on custom domains anyway.
  2. Create an origin subdomain, for example wf.example.com, add it under Site settings > Publishing > Production, and set it as the default domain. The proxy fetches pages from this hostname. If the default domain is not the origin, you get redirect loops.
  3. Set the global canonical URL under Site settings > SEO to your public URL, including https:// and the path if there is one (https://example.com/blog). This tells search engines which version counts, since the origin subdomain is reachable too.
  4. Turn on the auto-generated sitemap and enable Use your global canonical URL as the base URL for each sitemap.xml entry, so the sitemap lists public URLs instead of origin URLs.
  5. Set an Href prefix if Webflow content lives under a path. Under Site settings > Custom code > Advanced settings, set it to your public base (/blog or https://example.com/blog) so internal links point to /blog/.... It does not change external links, links from Link, Email or Phone CMS fields, or links in custom code. Those need the HTML rewriting described later.
  6. Do not use a <base> tag to fix links. Webflow notes it rewrites every relative URL and breaks the legacy Editor login, which has to load from the Webflow-connected subdomain.
  7. Plan robots.txt and the sitemap on the public domain. Webflow’s generated robots.txt points at the default domain, which is now the origin. Host your own on the main domain and route or bypass them explicitly. The options are covered in their own section below.
  8. Publish and confirm the origin works on its own. https://wf.example.com/ should serve the site with no redirect before you touch the proxy. Webflow Support can confirm the origin responds correctly; that is the one thing they will help with.

Setup Path 1: Next.js Rewrites (Vercel)

If your root site is a Next.js app, you already have a reverse proxy. Next.js rewrites forward matching paths to another URL without changing what the visitor sees, and Vercel documents them as a supported way to proxy external services. No Worker, no extra vendor, and the config lives in your repository next to everything else.

Publish Webflow on the origin subdomain, set the Href prefix to /blog and the canonical to https://example.com/blog, then add this to next.config.js:

JavaScript

// next.config.js
const WEBFLOW_ORIGIN = "https://wf.example.com";

module.exports = {
  async rewrites() {
    return [
      // The index route needs its own rule; /blog/:path* does not match /blog
      { source: "/blog", destination: `${WEBFLOW_ORIGIN}/` },
      { source: "/blog/:path*", destination: `${WEBFLOW_ORIGIN}/:path*` },
      // Assets Webflow references by absolute URL do not need a rule;
      // they load from cdn.prod.website-files.com directly.
    ];
  },
};

Three things to know:

  • Two rules, not one. /blog/:path* does not match /blog itself. Without the first rule the blog index returns your app’s 404.
  • Query strings pass through by default, which Webflow site search and CMS filters need. Do not add a rewrite that strips them.
  • Redirects from Webflow come back with the origin hostname. If you set up a 301 in Webflow from /old-post to /new-post, the Location header says wf.example.com/new-post. Next.js rewrites do not rewrite response headers. Either recreate the redirects in next.config.js redirects() on the public path, or add a middleware that rewrites the Location header. Most teams recreate them, since they own the redirect list anyway.

For a staged migration, where Next.js serves the pages it has and Webflow serves everything else, use the fallback form. Next checks its own routes and static files first, then proxies whatever is left:

JavaScript

module.exports = {
  async rewrites() {
    return {
      fallback: [
        { source: "/:path*", destination: "https://wf.example.com/:path*" },
      ],
    };
  },
};

If your app is not Next.js but runs on Vercel, the same thing goes in vercel.json:

JSON

{
  "rewrites": [
    { "source": "/blog", "destination": "https://wf.example.com/" },
    { "source": "/blog/:path*", "destination": "https://wf.example.com/:path*" }
  ]
}

Limits of this path: you cannot rewrite HTML on the way through, so any absolute origin URL that the Href prefix does not catch (Link fields, custom code, hreflang from Localization) stays as it is. If you need that, put a Cloudflare Worker in front or use Next.js middleware to post-process the response.

Setup Path 2: Cloudflare Workers

A Worker is a small script that runs on Cloudflare’s network before the request reaches any origin. You attach it to a route such as example.com/blog* and it decides where each request goes, what headers to send, and what to change in the response. It is the most flexible option and the right one for multi-domain routing, HTML rewriting and staged migrations where the root site is not on Vercel.

Webflow’s own hosting runs on Cloudflare. That matters for two reasons: the edge-to-origin hop is short, and the SSL story is simpler than it used to be.

SSL and DNS, explained once

The public domain’s certificate belongs to whoever terminates the connection, which is now the proxy, not Webflow. Webflow manages SSL only for hostnames pointed directly at it, which is your origin subdomain. So:

  • wf.example.com points at Webflow (cdn.webflow.com after the Cloudflare migration) and Webflow issues its certificate.
  • example.com points at your proxy. If that is Cloudflare, Cloudflare issues the certificate. If it is Vercel or your own server, they do.

If your whole domain is on Cloudflare, Webflow recommends Orange-to-Orange (O2O). The sequence matters: update the CNAME to cdn.webflow.com only when the Webflow Dashboard prompts you, keep the record DNS-only until Webflow shows SSL Active, then switch the record to Proxied and set Cloudflare SSL to Full (Strict). No Enterprise plan or custom certificate is needed.

One thing Webflow’s doc says in a note that most people miss: O2O is not a reverse proxy. It proxies traffic to a Webflow-hosted hostname at the DNS layer. For any path or domain rewrite (example.com/blog to wf.example.com), you still need a Worker.

You will find older guides (Finsweet’s proxy repository, the.com’s write-up) that point the origin at proxy.webflow.com and use Cloudflare’s Flexible SSL mode, or that tell you to disable SSL in Webflow’s advanced publishing options. Those were workarounds from before Webflow moved hosting to Cloudflare. Do not copy them today. Use the O2O sequence above.

A production Worker for a subdirectory

This serves a Webflow site published on wf.example.com at example.com/blog. Attach it to the route example.com/blog*. It maps paths, forwards query strings, sets the origin Host explicitly, rewrites redirects, passes real 404s through, and fixes stray absolute origin URLs in the HTML.

JavaScript

const PUBLIC_HOST = "example.com";
const PUBLIC_PREFIX = "/blog";
const ORIGIN_HOST = "wf.example.com";
const ORIGIN = `https://${ORIGIN_HOST}`;

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

    // /blog and /blog/ both map to the origin root; /blog/post maps to /post
    let originPath = url.pathname.slice(PUBLIC_PREFIX.length);
    if (originPath === "" ) originPath = "/";

    const originUrl = new URL(originPath + url.search, ORIGIN);

    // Build the outgoing request: explicit Host, keep the visitor's IP and UA
    const headers = new Headers(request.headers);
    headers.set("Host", ORIGIN_HOST);
    headers.set("X-Forwarded-Host", PUBLIC_HOST);
    headers.set("X-Forwarded-Proto", "https");
    headers.delete("cf-connecting-ip");

    const originResponse = await fetch(originUrl, {
      method: request.method,
      headers,
      body: request.body,
      redirect: "manual",
    });

    // Rewrite redirects so visitors never land on the origin hostname
    const location = originResponse.headers.get("Location");
    if (location) {
      const target = new URL(location, ORIGIN);
      if (target.hostname === ORIGIN_HOST) {
        const h = new Headers(originResponse.headers);
        const path = target.pathname === "/" ? "" : target.pathname;
        h.set("Location", `https://${PUBLIC_HOST}${PUBLIC_PREFIX}${path}${target.search}`);
        return new Response(originResponse.body, { status: originResponse.status, headers: h });
      }
    }

    // Non-HTML responses (CSS, JS, XML, images) pass through untouched
    const contentType = originResponse.headers.get("Content-Type") || "";
    if (!contentType.includes("text/html")) return originResponse;

    // Fix any absolute origin URL that the Href prefix did not catch:
    // canonical, og:url, hreflang, links in Link fields, custom code
    const rewriter = new HTMLRewriter()
      .on("a[href], link[href]", new UrlAttr("href"))
      .on("meta[content]", new UrlAttr("content"))
      .on("form[action]", new UrlAttr("action"));

    return rewriter.transform(originResponse);
  },
};

class UrlAttr {
  constructor(attr) { this.attr = attr; }
  element(el) {
    const v = el.getAttribute(this.attr);
    if (!v || !v.startsWith(ORIGIN)) return;
    const rest = v.slice(ORIGIN.length);
    el.setAttribute(this.attr, `https://${PUBLIC_HOST}${PUBLIC_PREFIX}${rest === "/" ? "" : rest}`);
  }
}

What it handles:

  • Path mapping. /blog/post becomes /post on the origin, which matches the Href prefix setup.
  • Host header. Set explicitly, which is what Webflow’s own NGINX reference does. Forwarding the public Host is the usual cause of 404s at the origin.
  • Query strings. Passed through, so site search and CMS filters work.
  • Redirects. Webflow 301s are rewritten to the public URL instead of exposing wf.example.com.
  • Status codes. A Webflow 404 comes back as a 404, not a 200 with an error page in it.
  • Absolute origin URLs in HTML. Rewritten on the way through. This is what makes Localization’s hreflang tags and links from CMS Link fields correct.

What it does not handle, and you should decide on:

  • Caching. Covered in its own section below. Test that a Webflow publish shows up on the public URL within a reasonable time.
  • Large responses. Webflow notes a 2 MB limit on origin responses through Cloudflare. Pages with huge inline SVGs or embedded JSON can hit it.
  • robots.txt and sitemap.xml. Add bypass routes or handle them in the Worker; see the sitemap section.
  • Rate limiting and bot rules. If you run Cloudflare WAF or Bot Fight Mode, make sure Googlebot can reach the route. A blocked crawler is the most common reason a page loads for you and fails the Search Console live test.

Test on a staging route (staging.example.com/blog*) before switching the production route on, and check the rendered HTML, not just the browser view.

Multi-domain routing from one Webflow project

For a setup like Hoovest, where several business-line domains are served from a single project, the Worker reads the incoming hostname and maps it to a folder in Webflow. The logic is the same as above with a lookup table instead of a single prefix. Each domain is attached to the Worker as its own route, and each maps to a Webflow folder that holds that business line’s pages.

JavaScript

const ORIGIN_HOST = "wf.example.com";
const ORIGIN = `https://${ORIGIN_HOST}`;

// Public hostname -> folder in the Webflow project
const SITES = {
  "brand-a.com": "/brand-a",
  "brand-b.com": "/brand-b",
  "brand-c.com": "/brand-c",
};

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const folder = SITES[url.hostname.replace(/^www\./, "")];
    if (!folder) return new Response("Unknown host", { status: 404 });

    const originUrl = new URL(folder + url.pathname + url.search, ORIGIN);
    // ...same fetch, redirect, and HTML rewriting as the subdirectory Worker,
    // with PUBLIC_PREFIX replaced by "" and the folder stripped from links.
  },
};

Two design choices to make early:

  • Folder per domain or collection per domain. Folders are simpler for static pages and give each domain a clean root. Collections are better when every domain shares the same page types (news, team, offices) and only the content differs. Hoovest uses one CMS with content tagged by business line, which lets the internal team publish across domains without duplicating templates.
  • Shared pages. Legal pages, the contact form and the 404 usually need to exist once and be served on every domain. Either keep them at the project root and map them explicitly in the Worker, or duplicate them per folder and accept the maintenance.

Set the global canonical per page for multi-domain projects (Webflow allows per-page override), or handle canonicals in the Worker’s HTML rewriter based on the incoming hostname. Otherwise every domain canonicalises to whichever one you typed into the global setting.

Setup Path 3: Webflow Cloud

Webflow Cloud deploys Next.js and Astro apps inside your Webflow workspace and mounts them under a path of an existing Webflow site. If the thing you want at example.com/app is a Next.js or Astro project, this removes the need for a proxy: Webflow serves the marketing site at the root and the app at the mount path, on the same domain, with one publish flow.

It also solves the “third-party tool under a Webflow site” case. Webflow publishes a subdirectory reverse proxy example: a small Next.js app that proxies every HTTP method from a mount path to a target URL set in an environment variable, deployable to Webflow Cloud. Point it at your help desk or docs tool and the content appears under your Webflow domain without a Cloudflare account.

Limits: Webflow Cloud is for code you deploy from a Git repository. It does not proxy a second Webflow project under the first, and it does not do multi-domain routing. Plan and pricing details change; check Webflow’s current Cloud pricing before committing.

Setup Path 4: NGINX and CloudFront

If your infrastructure team already runs NGINX or AWS, Webflow’s help centre has reference settings for both.

The NGINX block Webflow publishes, with the lines that matter:

server {
  server_name example.com;
  set $backend "wf.example.com";
  resolver 8.8.8.8 valid=60s;

  location / {
    proxy_set_header Host $backend;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_ssl_server_name on;
    proxy_pass https://$backend$request_uri;
    proxy_ignore_headers Cache-Control Expires;
  }

  # If you host these yourself on another origin
  location = /robots.txt  { proxy_pass https://app.example.com; }
  location = /sitemap.xml { proxy_pass https://app.example.com; }
}
  • proxy_ssl_server_name on is required. Without SNI, Cloudflare (which fronts Webflow hosting) can block the request as domain fronting.
  • resolver ... valid=60s makes NGINX re-resolve the origin, which matters because Webflow’s IPs change.
  • No trailing slash on proxy_pass. Webflow calls this out; https://$backend/ breaks path forwarding.
  • For a subdirectory, add a location /blog/ block that strips the prefix, or use the Href prefix and publish Webflow pages under the same path structure.

For CloudFront, Webflow’s guidance is blunt: disable caching on CloudFront. A Webflow publish purges Webflow’s Cloudflare cache but not CloudFront’s, so with caching on, visitors get stale pages until the CloudFront TTL runs out. Set the cache behaviour to forward all requests with TTL 0, forward query strings and the headers you need in the origin request policy, and only reach for Lambda@Edge if you need routing logic CloudFront cannot express.

Setup Path 5: Managed Tools

Subfold, Subpath and similar services let you add a “rewrite” in a dashboard: main site at the root, another Webflow site at /blog, a third at /careers, then point your domain at their infrastructure. For a team with no engineers and a simple requirement it is the fastest route, and they handle SSL and caching for you.

What you give up: another vendor in the request path, a monthly fee for as long as the site exists, no HTML rewriting or custom logic, and a migration project if the vendor changes terms or shuts down. Check who owns the DNS and how you would leave before signing up.

What Breaks Behind a Proxy

This is the section nobody publishes. Webflow features that talk back to Webflow’s servers with a check on the page’s hostname, or that assume Webflow controls the domain, do not survive the proxy. Test each row on staging before launch.

Feature Behind a proxy Notes
Static pages and CMS pages Works The core case
Internal links Works with Href prefix Link, Email and Phone fields and custom code need HTML rewriting
Site search Works if query strings are forwarded Broken search is the first sign query strings are being dropped
CMS filters and pagination Works if query strings are forwarded Same cause
Webflow forms Works, test it Forms post from the browser to Webflow’s API, so the proxy is not involved. Test reCAPTCHA and the redirect-after-submit URL, which may point at the origin
301 redirects set in Webflow Works if the proxy rewrites Location Otherwise visitors land on the origin hostname
Localization Works with rewriting Auto-generated hreflang tags reference the origin domain and must be rewritten. 301 rules do not apply to locale subdirectories automatically
Webflow Ecommerce Does not work Cart and checkout validate the page’s host with CSRF tokens and reject actions from the proxied path (documented by Finsweet from their own setup)
Webflow Memberships / Users Assume it does not work Same class of host validation. We have not found a working proxied setup
Legacy Editor login Works unless you add a base tag Webflow’s doc is explicit on this
Password-protected pages Test before launch Depends on cookie scope; unconfirmed
Webflow Analyze and Optimize Test before launch Scripts load from the page, so they should run, but attribution to the right hostname is unconfirmed
Assets (images, CSS, JS) Works Served from Webflow’s asset CDN by absolute URL, not through your proxy
Staging domain (*.webflow.io) Not allowed Against Terms of Service and features are disabled

If any “does not work” row is on your requirement list, the answer is a subdomain for that part of the site, or a full move to Webflow, not a proxy.

Caching and the Publish Problem

Every proxy adds a cache, whether you asked for one or not, and Webflow only purges its own.

  • Cloudflare caches proxied responses by default. Finsweet’s documentation of their production setup puts it at around four hours for proxied Webflow assets. Publish in Webflow and the public URL keeps serving the old page until the TTL expires.
  • CloudFront has the same problem, which is why Webflow says to disable caching there.
  • Vercel rewrites do not cache the upstream response by default unless the origin sends cache headers, but check with your framework version.
  • NGINX caches nothing unless you configure proxy_cache. Do not.

Fix for Cloudflare: purge on publish. Webflow fires a site_publish webhook whenever you publish. Point it at a small endpoint that calls Cloudflare’s cache purge API for your zone. Webflow’s own Cloudflare integration page describes exactly this pattern. A second Worker does the job:

JavaScript

// Purge worker: receives Webflow's site_publish webhook, purges the zone
export default {
  async fetch(request, env) {
    if (request.method !== "POST") return new Response("Method not allowed", { status: 405 });

    // Basic shared-secret check so nobody else can purge your cache
    if (request.headers.get("X-Purge-Secret") !== env.PURGE_SECRET) {
      return new Response("Forbidden", { status: 403 });
    }

    const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${env.ZONE_ID}/purge_cache`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${env.CF_API_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ purge_everything: true }),
    });

    return new Response(res.ok ? "Purged" : "Purge failed", { status: res.ok ? 200 : 500 });
  },
};

Register the Worker’s URL as the webhook in Webflow under Site settings > Apps and integrations > Webhooks, with the site_publish trigger. Webflow’s webhook does not send custom headers, so the shared secret has to go in the URL as a query parameter, or you validate Webflow’s signature instead. Teams that would rather not deploy a second Worker can do the same with a Make.com scenario: Webflow “Site published” trigger, HTTP module calling the purge endpoint.

Purge everything is fine for a marketing site. Purge by URL if the zone also serves an app whose cache you do not want to drop on every blog publish.

Sitemap and robots.txt

Webflow generates one robots.txt and one sitemap per site, and both are built around the default domain, which is now the origin subdomain. You have three options.

Option How it works Use when
Webflow-generated sitemap with canonical base Turn on the sitemap setting that uses the global canonical URL as the base. Every entry lists the public URL. Route /blog/sitemap.xml through the proxy Webflow is the only thing under the path and you do not need one combined sitemap
Self-hosted sitemap and robots on the main domain Serve robots.txt and sitemap.xml from your app or a static file at the root. The proxy bypasses those two paths Your root site is an app with its own sitemap and you want one robots.txt to rule everything
Sitemap index on the main domain A sitemap index at example.com/sitemap.xml lists the app’s sitemap and the Webflow one (proxied at /blog/sitemap.xml) Two or more sources of URLs and you want Search Console to see them all from one submission

Whichever you pick, the main-domain robots.txt should reference the sitemap that lists public URLs, and nothing should reference the origin.

The origin subdomain itself is the harder problem. Webflow cannot serve a different robots.txt per hostname, so wf.example.com/robots.txt says the same thing as the public one and the origin stays crawlable. Canonicals handle it in most cases: every origin page points at its public URL, so Google consolidates. Check site:wf.example.com a few weeks after launch. If pages show up, the canonical is missing or wrong on those pages.

The clean fix, if the origin is on Cloudflare via O2O, is to lock the origin so only your proxy can read it. A Worker on the wf.example.com route checks for a shared secret header that your proxy adds and returns 403 to everyone else, including crawlers. The public path keeps working because the proxy sends the header. Duplicate content stops being a thing you manage and becomes a thing that cannot happen. Treat this as an advanced step, test the Webflow Editor and Designer preview afterwards, and document it in the runbook, because a future engineer who removes the header will take the site down.

Localization Behind a Proxy

Webflow Localization routes locales as subdirectories by default: /fr/, /de/, with hreflang tags generated automatically for every page and included in the sitemap. Behind a proxy there are two cases.

Locale subdirectories under a prefix. The public URLs become example.com/blog/fr/post. The Worker’s path mapping already handles it, since /fr/post is just a deeper path on the origin. What does not work on its own is hreflang: Webflow generates <link rel="alternate" hreflang="fr" href="https://wf.example.com/fr/post"> with the origin hostname (a Webflow forum thread from 2023 describes exactly this, and the behaviour has not changed). The HTML rewriter in the production Worker above fixes it, because it rewrites every link[href] that starts with the origin. Verify in view-source on one page per locale, then in Search Console’s International targeting report.

One domain per language. This is what the Webflow forum keeps asking for under titles like “Different top-level domains for each locale” and “Separate domains for localisations”, and it is what Hoovest needed alongside its business-line domains: English, French and Chinese content, with domains that make sense in each market. Webflow does not support it natively. The proxy does the mapping: example.ca to the English locale, example.fr to /fr/, and so on, with the hreflang set rewritten so each alternate points at the right domain rather than a locale path. We cover the setup and its SEO implications in a separate guide to running a different domain for each language on Webflow (in progress; link when live).

One more Localization gotcha that has nothing to do with the proxy but bites during migrations: Webflow’s 301 rules are relative to the root and do not apply to locale subdirectories. A redirect from /old to /new needs a matching rule for /fr/old to /fr/new.

Staged Migration with a Proxy

The proxy is also the least risky way to move a large site to Webflow section by section. Instead of one launch weekend, the routing table changes a little each week.

  1. Publish the new Webflow site on the origin subdomain with the first section built (usually the blog, since it is CMS-heavy and self-contained).
  2. Route that section’s path to Webflow and leave every other path pointing at the old platform. With Next.js, that is the fallback rewrite. With a Worker, it is a path list.
  3. Build the redirect map per section, not per site. Only the URLs that changed in the migrated section get 301s. Everything else keeps working because it never moved.
  4. Extend the sitemap as sections move: the sitemap index lists the old platform’s sitemap (with the moved section removed) and the Webflow sitemap (with only the moved section).
  5. Watch Search Console per section. A drop confined to the moved paths is a migration problem. A drop everywhere is a proxy or caching problem.
  6. Cut over the root last. When the homepage and the remaining static pages are in Webflow, flip the default route, retire the old platform, and decide whether the proxy stays (you still have an app under a path) or goes (point the domain straight at Webflow and drop the moving part).

The Webflow forum has threads asking for exactly this (“partial Webflow migration using reverse proxy”, “WordPress to Webflow with some content”) with no complete answer. The order above is what we run.

Performance: What the Extra Hop Costs

A proxy adds a hop between the visitor and Webflow. How much it costs depends on where the hop is.

  • Cloudflare Worker with Webflow on Cloudflare: the request goes edge to edge inside one network. Expect single-digit milliseconds of added time to first byte in our measurements, often hidden by Cloudflare’s cache on the second request.
  • Vercel rewrite: Vercel’s edge fetches from Webflow’s edge. Low tens of milliseconds is typical, more if the Vercel region and the visitor are far apart and the page is not cached.
  • NGINX on a single VPS: every visitor, everywhere, goes through one server in one region, then out to Webflow. This is where a proxy undoes the Core Web Vitals gain that the move to Webflow was meant to deliver. If you must use NGINX, put a CDN in front of it.
  • CloudFront with caching disabled: every request goes to the origin. Fine for Webflow, since Webflow’s own CDN serves it, but the double round trip shows in TTFB.

Measure before and after: PageSpeed Insights and CrUX for LCP and TTFB on five representative pages, on the origin subdomain and on the public path. If the public path is more than 100 ms slower than the origin at the 75th percentile, look at the proxy’s region and cache settings before touching the site.

Cost

Prices change; check at the time of the decision. What to expect at marketing-site traffic levels:

Path Typical cost Hidden cost
Next.js / Vercel rewrites Included in your Vercel plan None beyond what you pay already
Cloudflare Workers Free tier covers a marketing site; the paid plan is a few dollars a month Cloudflare account ownership, someone who can edit Workers
Webflow Cloud Part of Webflow plans, with usage limits Git-based deploys; not for non-developers
NGINX The server (from a few dollars a month) Patching, uptime, a CDN if you care about speed
CloudFront Per request and per GB, low at this scale AWS account, IAM, someone who knows CloudFront
Subfold and similar Monthly subscription Vendor dependency, exit cost

The real cost is ownership. Every path except Webflow Cloud and the managed tools means someone on your side is responsible for a piece of infrastructure that Webflow will not debug. Budget for the person, not the tool.

SEO Checklist for a Proxied Webflow Site

A reverse proxy is invisible to visitors, but search engines see every mistake. Run these before launch and again a week after.

Check What good looks like How to verify
Canonical tags Every page points to its public URL View source on 5 to 10 pages, including one per locale
Sitemap All loc entries use the public domain and path Open the sitemap your robots.txt references
robots.txt Served on the public domain, references the public sitemap curl example.com/robots.txt
Redirects One hop from any old URL to the public URL, never via the origin curl -I on old URLs
Origin subdomain Not linked from anywhere, canonicalised to public URLs, or locked Search site:wf.example.com after a few weeks
Status codes 200 on real pages, 404 on missing ones, through the proxy Crawl the public path with Screaming Frog
Query strings Site search and filtered collections work Search for a term, apply a filter
Forms A real submission lands in Webflow and the thank-you redirect stays on the public domain Submit a test entry
Google’s view Live URL test passes in Search Console URL Inspection > Test live URL
hreflang Alternate URLs use public domains and paths View source, then Search Console
Cache A publish shows on the public URL within minutes Publish a visible change, reload, check cf-cache-status headers
Analytics One GA4 property, no self-referrals from the origin GA4 traffic acquisition report

The Search Console live test is the check most teams skip, and the one that matters most. A proxy can return a working page to a browser and a different response to Googlebot, from a cached error on a specific device variant, a bot rule, or a header the crawler does not send. If the live test fails while the page loads for you, look at the proxy and CDN rules before touching content.

Three curl commands cover most of the checklist:

Shell

# Public path returns 200 and the right canonical
curl -sI https://example.com/blog/ | head -20
curl -s https://example.com/blog/ | grep -i 'rel="canonical"'

# A Webflow redirect is rewritten to the public host, not the origin
curl -sI https://example.com/blog/old-post | grep -i location

# Googlebot gets the same status as you
curl -sI -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.com/blog/

Common Mistakes

  • Leaving the origin subdomain uncanonicalised. Google finds both versions and guesses.
  • Proxying the staging webflow.io domain. Against Webflow’s terms, and features silently stop working.
  • Forwarding the public Host header to Webflow. Webflow returns 404 because it does not know the hostname. Set Host to the origin.
  • Not setting the origin as the default domain. Webflow redirects to whatever the default is, the proxy follows, and you get a loop.
  • Double caching. A CDN in front of Webflow’s CDN, both caching HTML, means publishes appear hours late.
  • Absolute links to the origin. Hard-coded links in rich text, Link fields or custom code bypass the Href prefix. Rewrite them at the proxy.
  • Forgetting forms and search. Test a real submission and a real search through the proxy, not just page loads.
  • Proxying an ecommerce or members section. It will fail at checkout or login, after the launch, in front of a customer.
  • No purge on publish. Editors think the publish failed, republish five times, and open a support ticket with Webflow about a cache Webflow does not control.
  • No owner. The proxy needs someone who knows it exists. Document the routes, the code, the Webflow settings and the rollback in the handover.

Operations: Runbook, Rollback, Monitoring

Write a one-page runbook before launch and keep it with the code:

  • Where the proxy runs (Cloudflare account and zone, Vercel project, or server), who has access, and where the code lives.
  • The routing table: every public path or hostname and where it goes.
  • The Webflow settings that must not change: default domain, canonical, Href prefix, sitemap base setting.
  • The purge mechanism and how to purge manually.
  • Rollback: for a Worker, disable the route (not DNS) and the path falls through to whatever is behind it; for Next.js, revert the rewrite and redeploy; for NGINX, comment the location block and reload. Rollback should take under five minutes and not touch DNS.
  • Monitoring: an uptime check on one public path that alerts on non-200, and a weekly Search Console glance at the origin subdomain and at coverage for the proxied section.

Case Study: Hoovest

Hoovest is a Canadian integrated financial group covering investments, insurance, fund management, corporate advisory, real estate and family office services. It needed separate domains for distinct business lines, a consistent experience across them, and content in English, French and Chinese.

In 12 weeks, Skywwward delivered:

  • A full Webflow rebuild replacing a legacy WordPress site, including UX and UI design
  • One design system and CMS serving multiple business-line domains
  • Cloudflare Worker routing to serve those domains from a single Webflow project
  • A trilingual CMS structure the internal team manages without developers
  • QA across templates, languages, devices and key flows, plus documentation and training at handover

The result is one governed system instead of several sites drifting apart, which keeps content, design and SEO settings consistent as the business adds initiatives. The hostname lookup table pattern above is the shape of that routing, and the per-domain canonical handling is the setting that took the most care.

Conclusion

A Webflow reverse proxy puts Webflow content on the URL structure your business needs: a blog under a Next.js app, docs under a Webflow marketing site, several brands from one project, or a migration done a section at a time. Webflow gives you the settings. The routing, the cache, the sitemap and the checks are yours.

Pick the lightest path that fits who owns the root site: Next.js rewrites if the root is on Vercel, Webflow Cloud if the root is Webflow and the addition is an app, a Cloudflare Worker for everything that needs real routing or HTML rewriting. Do not proxy ecommerce or members. Purge on publish. Lock or canonicalise the origin. Confirm with Search Console that Google sees the page your visitors see.

Skywwward builds and maintains Webflow sites with custom routing and integrations, including multi-domain setups like Hoovest. If you are planning a reverse proxy, a subdirectory move, or a migration to Webflow, tell us what you are building and we will look at the right setup.

Changelog. September 2026: rewritten as a full guide. Added Next.js and Vercel rewrites, SSL and Orange-to-Orange sequence, production Worker with HTML rewriting, multi-domain routing, the compatibility table, purge-on-publish, sitemap options and origin lockdown, Localization behind a proxy, staged migrations, performance, cost, runbook. First published 18 September 2026.

Sources

<anchor-link>
Written by
Hunor
Hunor
Founder
,
Lead Developer
September 18, 2026
Share

Frequently asked questions

Does Webflow support reverse proxies?

Yes, on paid Site plans with a custom domain. Webflow documents the required settings (origin subdomain, global canonical, sitemap base URL and Href prefix), but it does not configure or troubleshoot the proxy itself. Webflow Support can confirm the origin responds correctly. Enterprise customers can ask Webflow Sales about direct help.

Can I host a Webflow blog on a subdirectory like example.com/blog?

Yes. Publish the Webflow site on an origin subdomain, set the Href prefix to /blog and the global canonical URL to https://example.com/blog, then route example.com/blog through Next.js rewrites, a Cloudflare Worker, NGINX or CloudFront.

Should I use Next.js rewrites or a Cloudflare Worker?

If your root site is a Next.js app on Vercel, use rewrites; the config lives in your repository and there is nothing new to host. Use a Worker when you need to rewrite HTML (Localization, Link fields), route several domains, or when the root site is not on Vercel.

Is a subdirectory better than a subdomain for SEO?

Google says it handles both. A subdirectory keeps content, internal links, sitemaps and reporting on one domain, which is simpler to manage. It is not a ranking shortcut, and a badly configured proxy does more harm than a clean subdomain.

Does a reverse proxy slow down a Webflow site?

A little, and how much depends on the path. A Cloudflare Worker in front of Webflow's Cloudflare hosting adds single-digit milliseconds. A single NGINX server in one region can add hundreds of milliseconds for visitors elsewhere. Measure TTFB on the origin and the public path and compare.

Does Webflow Ecommerce work behind a reverse proxy?

No. Cart and checkout validate the page's hostname and reject actions coming from the proxied path. Keep the store on a domain pointed directly at Webflow, or use a different platform for the store.

Do Webflow forms work behind a reverse proxy?

Yes. Forms post from the visitor's browser to Webflow's API, so the proxy is not in the path. Test reCAPTCHA and the redirect-after-submit URL, which can point at the origin if it was set with an absolute URL.

Can I proxy my webflow.io staging domain?

No. Webflow's Terms of Service prohibit it and several features only work on custom domains. Publish to a custom origin subdomain on a paid Site plan.

Why do my changes not show up after publishing?

Your proxy or CDN is caching the old page. Webflow purges its own cache on publish, not yours. Set up a purge on Webflow's site_publish webhook, or disable caching on the proxy layer.

Can one Webflow project serve multiple domains?

Not natively, but a routing layer can do it. Skywwward built this for Hoovest, a financial group with several business lines, using Cloudflare Worker routing to serve separate domains from one Webflow project with one design system and a trilingual CMS.

Does Webflow Localization work behind a reverse proxy?

Yes, with one fix: the hreflang tags Webflow generates reference the origin domain and have to be rewritten at the proxy. Locale subdirectories map through like any other path. One domain per language is possible with hostname routing.

What is the easiest way to run a Next.js app under a Webflow site?

Webflow Cloud. It deploys Next.js and Astro apps from your Git repository and mounts them under a path of your Webflow site, so you do not need to build and host a separate proxy.

How long does a Webflow reverse proxy setup take?

A single subdirectory route with Next.js rewrites or a Cloudflare Worker can be live in a few days, including SEO checks. Multi-domain routing combined with a full rebuild takes longer. Hoovest's multi-domain, trilingual rebuild took 12 weeks from design to handover.

Working on something similar?

Tell us what you're building.
We'll weigh in on the hard parts.

Start the conversation