Deploy at a subpath with Cloudflare Workers
Deploy your Mintlify documentation at a subpath on your domain using Cloudflare Workers with step-by-step setup and DNS configuration.
To host your documentation at a subpath such as yoursite.com/docs using Cloudflare, you must create and configure a Cloudflare Worker.
Set your base path
Section titled “Set your base path”- Navigate to the Custom domain setup page in your dashboard.
- Enable the Host at toggle.
- Enter your domain.
- Enter your base path. For example,
/docsor/help. - Click Add domain.
The dashboard displays a Cloudflare Worker script with your subdomain, domain, and base path filled in. Use this script in the Configure routing step instead of manually replacing the placeholder values in the example script.
Set up a Worker
Section titled “Set up a Worker”Create a Cloudflare Worker by following the Cloudflare Workers getting started guide, if you have not already.
Proxies with Vercel deployments
Section titled “Proxies with Vercel deployments”If you use Cloudflare as a proxy with Vercel deployments, you must ensure proper configuration to avoid conflicts with Vercel's domain verification and SSL certificate provisioning.
Improper proxy configuration can prevent Vercel from provisioning Let's Encrypt SSL certificates and cause domain verification failures.
Required path allowlist
Section titled “Required path allowlist”Your Cloudflare Worker must allow traffic to these specific paths without blocking or redirecting:
/.well-known/acme-challenge/*: Required for Let's Encrypt certificate verification./.well-known/vercel/*: Required for Vercel domain verification.
While Cloudflare automatically handles many verification rules, creating additional custom rules may inadvertently block this critical traffic.
Header forwarding requirements
Section titled “Header forwarding requirements”Ensure that your Worker sets the Host header to your <subdomain>.mintlify.site target, as shown in the example script, rather than passing through the original request's Host header. Incorrect Host headers cause verification requests to fail.
Configure routing
Section titled “Configure routing”In your Cloudflare dashboard, click Edit Code and add the script from your Custom domain setup page, which has your values filled in, or copy the following example script. See the Cloudflare documentation for more information on editing a Worker.
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
try {
const urlObject = new URL(request.url);
// If the request is to a Vercel verification path, allow it to pass through
if (urlObject.pathname.startsWith('/.well-known/')) {
return await fetch(request);
}
// If the request is to the docs subpath or a Mintlify asset or API path
if (
/^\/docs/.test(urlObject.pathname) ||
/^\/mintlify-assets\//.test(urlObject.pathname) ||
/^\/_mintlify\//.test(urlObject.pathname)
) {
// Then Proxy to Mintlify
const DOCS_URL = "[SUBDOMAIN].mintlify.site";
const CUSTOM_URL = "[YOUR_DOMAIN]";
let url = new URL(request.url);
url.hostname = DOCS_URL;
let proxyRequest = new Request(url, request);
proxyRequest.headers.set("Host", DOCS_URL);
proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
proxyRequest.headers.set("X-Forwarded-Proto", "https");
// If deploying to Vercel, preserve client IP
proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));
return await fetch(proxyRequest);
}
} catch (error) {
// If no action found, serve the regular request
return await fetch(request);
}
}Click Deploy and wait for the changes to propagate.
Test your Worker
Section titled “Test your Worker”After your code deploys, test your Worker to ensure it routes to your Mintlify docs.
- Test using the Worker's preview URL:
your-worker.your-subdomain.workers.dev/docs - Verify the Worker routes to your Mintlify docs and your website.
Add a custom domain
Section titled “Add a custom domain”- In your Cloudflare dashboard, navigate to your Worker.
- Go to Settings > Domains & Routes > Add > Custom Domain.
- Add your domain.
See Add a custom domain in the Cloudflare documentation for more information.
Resolve DNS conflicts
Section titled “Resolve DNS conflicts”If your domain already points to another service, you must remove the existing DNS record. Your Cloudflare Worker must control all traffic for your domain.
- Delete the existing DNS record for your domain. See Delete DNS records in the Cloudflare documentation for more information.
- Return to your Worker and add your custom domain.
Webflow custom routing
Section titled “Webflow custom routing”If you use Webflow to host your main site and want to serve Mintlify docs at /docs on the same domain, configure custom routing through Cloudflare Workers. The Worker proxies all non-docs traffic to your main site.
- In Webflow, set up a landing page for your main site like
landing.yoursite.com. This is the page that visitors see when they visit your site. - Deploy your main site to the landing page. This ensures that your main site remains accessible while you configure the Worker.
- To avoid conflicts, update any absolute URLs in your main site to be relative.
- In Cloudflare, click Edit Code and add the following script into your Worker's code.
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
try {
const urlObject = new URL(request.url);
// If the request is to a Vercel verification path, allow it to pass through
if (urlObject.pathname.startsWith('/.well-known/')) {
return await fetch(request);
}
// If the request is to the docs subpath or a Mintlify asset or API path
if (
/^\/docs/.test(urlObject.pathname) ||
/^\/mintlify-assets\//.test(urlObject.pathname) ||
/^\/_mintlify\//.test(urlObject.pathname)
) {
// Proxy to Mintlify
const DOCS_URL = "[SUBDOMAIN].mintlify.site";
const CUSTOM_URL = "[YOUR_DOMAIN]";
let url = new URL(request.url);
url.hostname = DOCS_URL;
let proxyRequest = new Request(url, request);
proxyRequest.headers.set("Host", DOCS_URL);
proxyRequest.headers.set("X-Forwarded-Host", CUSTOM_URL);
proxyRequest.headers.set("X-Forwarded-Proto", "https");
// If deploying to Vercel, preserve client IP
proxyRequest.headers.set("CF-Connecting-IP", request.headers.get("CF-Connecting-IP"));
return await fetch(proxyRequest);
}
// Route everything else to main site
const MAIN_SITE_URL = "[LANDING_DOMAIN]";
if (MAIN_SITE_URL && MAIN_SITE_URL !== "[LANDING_DOMAIN]") {
let mainSiteUrl = new URL(request.url);
mainSiteUrl.hostname = MAIN_SITE_URL;
return await fetch(mainSiteUrl, {
method: request.method,
headers: request.headers,
body: request.body
});
}
} catch (error) {
// If no action found, serve the regular request
return await fetch(request);
}
}- Click Deploy and wait for the changes to propagate.
Troubleshoot firewall blocking
Section titled “Troubleshoot firewall blocking”If your documentation site shows 500 errors after a few seconds or experiences slow navigation, Cloudflare's firewall may be blocking requests to Mintlify assets.
Symptoms
Section titled “Symptoms”- Documentation page loads initially but crashes with a 500 error after 30-60 seconds.
- Slow or broken client-side navigation between pages.
- 403 errors in the browser console for requests to
/mintlify-assets/*paths. - Cloudflare security challenge messages about "malformed data" or "suspicious URL patterns."
Root cause
Section titled “Root cause”Cloudflare's Web Application Firewall (WAF) and Bot Fight Mode can flag Mintlify asset requests as suspicious due to:
- Multiple
%symbols in encoded URL parameters. - Long query strings with special characters.
- Automated requests from idle tabs.
Solution
Section titled “Solution”Create a Cloudflare firewall rule to exempt Mintlify assets from security checks.
Create the firewall exception
Section titled “Create the firewall exception”- Log in to your Cloudflare dashboard.
- Select your domain.
- Navigate to Security > WAF.
- Click Create rule.
- Configure the rule with these settings:
Rule name: Allow Mintlify assets
When incoming requests match:
- Field:
Hostname - Operator:
equals - Value:
docs.yourdomain.com(replace with your actual docs domain)
And:
- Field:
URI Path - Operator:
starts with - Value:
/mintlify-assets/
Then:
- Action:
Skip - Select:
All remaining custom rules,Managed rules, andSuper Bot Fight Mode
- Enable Log to track matched requests.
- Click Deploy.
Verify the rule
Section titled “Verify the rule”After deploying:
- Open your documentation site in a browser.
- Leave the page idle for 2-3 minutes.
- Navigate between pages.
- Check the browser console for any 403 errors.
If issues persist, verify your rule configuration:
- Ensure the hostname exactly matches your docs domain.
- Confirm the URI path uses
starts with(notcontains). - Do not include wildcards (
*) in the path value. - Verify that you enabled and deployed the rule.
Common mistakes
Section titled “Common mistakes”- Using the
containsoperator with/mintlify-assets/*. The*is treated as a literal character, not a wildcard. - Using
equalsfor URI Path. This only matches the exact path/mintlify-assets/and not subpaths. - Forgetting to skip Bot Fight Mode. Explicitly include it in the skip action.
- Setting the wrong hostname. It must match your actual documentation domain.
Additional troubleshooting
Section titled “Additional troubleshooting”If the firewall exception doesn't resolve the issue:
- Check Cloudflare's Security > Events log for blocked requests.
- Verify that your Cloudflare Worker (if using a custom subpath) sets the
Hostheader to your<subdomain>.mintlify.sitetarget instead of passing through the original request'sHostheader. - Temporarily set Security Level to "Essentially Off" to confirm that Cloudflare is the cause.
- Review any custom Page Rules that might override the firewall exception.
Example working configuration
Section titled “Example working configuration”Rule: Allow Mintlify assets
Status: Enabled
When incoming requests match:
(http.host eq "docs.yourdomain.com" and starts_with(http.request.uri.path, "/mintlify-assets/"))
Then:
Skip: All remaining custom rules, Managed rules, Super Bot Fight Mode
Log: Enabled