Cloudflare Workers

Use Cloudflare Workers to serve your blog at a subpath like yoursite.com/blog. Workers intercept requests and route them to the appropriate destination based on the URL path.

You'll need a Cloudflare account and a domain (either managed on Cloudflare or elsewhere). If using Cloudflare for DNS, consider disabling proxying for CNAME records to avoid configuration conflicts.

Create a Cloudflare Worker

If you don't already have a Worker, create one through the Cloudflare dashboard:

  1. Log into your Cloudflare dashboard
  2. Navigate to Workers & Pages
  3. Click Create Worker
  4. Give your Worker a descriptive name
  5. Click Deploy to create the initial Worker

For detailed steps, see Cloudflare's Workers getting started guide.


Configure the Worker Script

Edit your Worker's code to route Waldium paths to your Waldium site. Replace [SUBDOMAIN] with your Waldium subdomain and [YOUR_DOMAIN] with your website's domain.

Paths routed to Waldium:

  • /blog — Your blog content
  • /waldium-assets — Static assets for your blog
  • /_waldium — Internal Waldium resources
  • /api/waldium-request — Waldium API endpoint
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  try {
    const url = new URL(request.url);

    // Route Waldium paths to Waldium
    if (
      url.pathname.startsWith("/blog") ||
      url.pathname.startsWith("/waldium-assets") ||
      url.pathname.startsWith("/_waldium") ||
      url.pathname === "/api/waldium-request"
    ) {
      const BLOG_URL = "[SUBDOMAIN].waldium.app";
      const CUSTOM_URL = "[YOUR_DOMAIN]";

      let proxyUrl = new URL(url.pathname + url.search, `https://${BLOG_URL}`);
      let proxyRequest = new Request(proxyUrl, request);

      proxyRequest.headers.set("Host", BLOG_URL);
      proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
      proxyRequest.headers.set("X-Forwarded-Proto", "https");
      proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));

      return await fetch(proxyRequest);
    }

    // Everything else passes through to origin
    return await fetch(request);
  } catch (error) {
    return await fetch(request);
  }
}

Click Deploy after adding the script.


Custom Subpath

By default, Waldium serves your blog at /blog. If you want to host it at a different path — for example, /articles or /news — you need to update the Worker script to rewrite paths and fix links in the HTML response.

The subpath you choose here must match the subpath you configure in your Waldium Domain Settings. For example, if you enter yoursite.com with subpath /articles in Waldium, your Worker must use /articles as the custom subpath.

Worker Script with Path Rewrite

Replace [SUBDOMAIN], [YOUR_DOMAIN], and the CUSTOM_SUBPATH value with your own:

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  try {
    const url = new URL(request.url);
    const CUSTOM_SUBPATH = "/articles"; // your chosen subpath

    if (
      url.pathname.startsWith(CUSTOM_SUBPATH) ||
      url.pathname.startsWith("/waldium-assets") ||
      url.pathname.startsWith("/_waldium") ||
      url.pathname === "/api/waldium-request"
    ) {
      const BLOG_URL = "[SUBDOMAIN].waldium.app";
      const CUSTOM_URL = "[YOUR_DOMAIN]";

      // Rewrite custom subpath to /blog for Waldium
      let waldiumPath = url.pathname + url.search;
      if (url.pathname.startsWith(CUSTOM_SUBPATH)) {
        waldiumPath = "/blog" + url.pathname.slice(CUSTOM_SUBPATH.length) + url.search;
      }

      let proxyUrl = new URL(waldiumPath, `https://${BLOG_URL}`);
      let proxyRequest = new Request(proxyUrl, request);

      proxyRequest.headers.set("Host", BLOG_URL);
      proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
      proxyRequest.headers.set("X-Forwarded-Proto", "https");
      proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));

      const response = await fetch(proxyRequest);

      // Rewrite /blog back to custom subpath in the HTML response
      return new HTMLRewriter()
        .on("a", {
          element(el) {
            const href = el.getAttribute("href");
            if (href && href.startsWith("/blog")) {
              el.setAttribute("href", CUSTOM_SUBPATH + href.slice(5));
            }
          }
        })
        .on("link", {
          element(el) {
            const href = el.getAttribute("href");
            if (href && href.startsWith("/blog")) {
              el.setAttribute("href", CUSTOM_SUBPATH + href.slice(5));
            }
          }
        })
        .on("script", {
          element(el) {
            const src = el.getAttribute("src");
            if (src && src.startsWith("/blog")) {
              el.setAttribute("src", CUSTOM_SUBPATH + src.slice(5));
            }
          }
        })
        .transform(response);
    }

    // Everything else passes through to origin
    return await fetch(request);
  } catch (error) {
    return await fetch(request);
  }
}

Why Path Rewriting Is Needed

Waldium always serves blog content at /blog internally. When you use a custom subpath like /articles:

User requestsWorker fetches from Waldium
/articles/blog
/articles//blog/
/articles/my-post/blog/my-post
/waldium-assets/.../waldium-assets/... (no rewrite)
/_waldium/.../_waldium/... (no rewrite)

The HTMLRewriter handles the reverse — rewriting /blog back to /articles in all links, stylesheets, and scripts so that URLs in the browser stay consistent.

Worker Routes (Path-Specific)

When your main site already runs on the same domain (e.g. a WordPress or marketing site), use path-specific Worker Routes instead of attaching a Custom Domain to the Worker. This ensures only Waldium paths hit the Worker while all other traffic goes directly to your origin.

  1. In Cloudflare, go to Domains → yoursite.com → Workers Routes
  2. Add one route per path pattern, selecting your Worker for each:
RouteWorker
yoursite.com/articlesyour-worker-name
yoursite.com/articles/*your-worker-name
yoursite.com/waldium-assets/*your-worker-name
yoursite.com/_waldium/*your-worker-name
yoursite.com/api/waldium-requestyour-worker-name

Replace /articles with your chosen subpath. If your site also uses www, add matching www.yoursite.com routes.

Path-specific Worker Routes are the recommended approach when another service (WordPress, Webflow, etc.) already handles the root domain. Using a Custom Domain on the Worker would route all traffic through it, which can cause loops or break the main site.


Vercel Integration Considerations

If your main site is deployed on Vercel, the Worker must allow certain paths for domain verification and SSL certificates:

Required path allowlist:

  • /.well-known/acme-challenge/* — Let's Encrypt certificate verification
  • /.well-known/vercel/* — Vercel domain verification

The script above passes all non-Waldium paths (including .well-known) through to your origin, so verification paths will work automatically. Ensure no additional rules block these paths.

Header forwarding: The Host header must be correctly set in the Worker. The example script handles this, but custom modifications could break verification.


Webflow and Other Site Builders

If your main site runs on Webflow or another platform, you'll need the Worker to handle all traffic—routing blog requests to Waldium and everything else to your main site.

Ensure your main site is accessible before deploying this Worker, or visitors will see errors.

  1. Set up a staging URL for your main site (e.g., landing.yoursite.com)
  2. Update the Worker to route non-blog traffic to your staging URL:
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  try {
    const url = new URL(request.url);

    // Route Waldium paths to Waldium
    if (
      url.pathname.startsWith("/blog") ||
      url.pathname.startsWith("/waldium-assets") ||
      url.pathname.startsWith("/_waldium") ||
      url.pathname === "/api/waldium-request"
    ) {
      const BLOG_URL = "[SUBDOMAIN].waldium.app";
      const CUSTOM_URL = "[YOUR_DOMAIN]";

      let proxyUrl = new URL(url.pathname + url.search, `https://${BLOG_URL}`);
      let proxyRequest = new Request(proxyUrl, request);

      proxyRequest.headers.set("Host", BLOG_URL);
      proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
      proxyRequest.headers.set("X-Forwarded-Proto", "https");
      proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));

      return await fetch(proxyRequest);
    }

    // Route everything else to your main site
    const MAIN_SITE_URL = "[LANDING_DOMAIN]";
    let mainSiteUrl = new URL(url.pathname + url.search, `https://${MAIN_SITE_URL}`);
    
    return await fetch(mainSiteUrl, {
      method: request.method,
      headers: request.headers,
      body: request.body
    });
  } catch (error) {
    return await fetch(request);
  }
}

Replace [LANDING_DOMAIN] with your staging URL (e.g., landing.yoursite.com).


Connect Your Domain

There are two ways to connect the Worker to your domain. Choose the one that fits your setup:

Option A: Custom Domain (Worker handles all traffic)

Use this when the Worker is the sole handler for the domain (e.g., Webflow or other site builder proxied through the Worker).

  1. In Cloudflare, navigate to your Worker
  2. Go to Settings > Domains & Routes > Add > Custom Domain
  3. Enter your domain (e.g., yoursite.com)

Add both yoursite.com and www.yoursite.com for complete coverage.

If your domain already has DNS records pointing elsewhere, you'll need to remove them first. The Worker must control all traffic for your domain.

Option B: Worker Routes (main site stays on origin)

Use this when another service (WordPress, a marketing site, etc.) already handles your root domain and you only want the Worker to intercept Waldium paths. See the Worker Routes table in the Custom Subpath section above for the exact routes to add.


Test Your Setup

Before going live, verify the Worker routes correctly:

  1. Test the Worker preview URL — Visit your-worker.your-subdomain.workers.dev/blog
  2. Confirm blog content loads — You should see your Waldium blog
  3. Check your main site — Ensure non-blog pages still work

DNS Propagation

After configuring your domain, changes typically appear within a few minutes. However, DNS propagation can take 1-4 hours, and occasionally up to 48 hours. If your subpath isn't working immediately, wait before troubleshooting.


Troubleshooting

IssueSolution
"Post not found" on custom subpathThe Worker must rewrite your custom path (e.g. /articles) to /blog when fetching from Waldium. Verify the CUSTOM_SUBPATH value and the pathname.slice() length match.
Links in the blog point to /blogAdd the HTMLRewriter to rewrite /blog back to your custom subpath in a, link, and script elements.
Main site returns 404 or loopsYou may have attached the domain as a Custom Domain on the Worker, routing all traffic through it. Use path-specific Worker Routes instead so only Waldium paths hit the Worker.
Assets (CSS/JS) not loadingEnsure Worker Routes include /waldium-assets/* and /_waldium/*.
"Domain already in use" errorThe domain is already attached as a Custom Domain to another Worker or zone. Use Worker Routes instead of Custom Domain attachment.

Was this page helpful?