Files
mintlify__docs/deploy/cloudflare.mdx
mintlify[bot] 8c0886aaf8 Clarify /docs subpath vs custom subpath setup (#1993)
* Update customize/custom-domain.mdx

* Update deploy/vercel.mdx

* Update deploy/cloudflare.mdx

* Update deploy/route53-cloudfront.mdx

* create overview for setting up /docs subpath

* add h3

* update vercel + move non-subpath content to new file

* correct Cloudflare page

* clean up AWS

* reviewer feedback

---------

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Co-authored-by: Ethan Palm <56270045+ethanpalm@users.noreply.github.com>
2025-12-03 09:52:33 -08:00

182 lines
7.4 KiB
Plaintext

---
title: "Cloudflare"
description: "Host documentation at a subpath on Cloudflare Workers."
keywords: ["Cloudflare Workers", "subpath routing", "reverse proxy setup", "Worker configuration"]
---
import Propagating from "/snippets/custom-subpath-propagating.mdx";
To host your documentation at a subpath such as `yoursite.com/docs` using Cloudflare, you must create and configure a Cloudflare Worker.
<Info>
Before you begin, you need a Cloudflare account and a domain name (can be managed on or off Cloudflare).
</Info>
## Set up a Cloudflare Worker
Create a Cloudflare Worker by following the [Cloudflare Workers getting started guide](https://developers.cloudflare.com/workers/get-started/dashboard/), if you have not already.
<Tip>
If your DNS provider is Cloudflare, disable proxying for the CNAME record to avoid potential configuration issues.
</Tip>
### 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
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
Ensure that the `HOST` header is correctly forwarded in your Worker configuration. Failure to properly forward headers will cause verification requests to fail.
### Configure routing
In your Cloudflare dashboard, select **Edit Code** and add the following script into your Worker's code. See the [Cloudflare documentation](https://developers.cloudflare.com/workers-ai/get-started/dashboard/#development) for more information on editing a Worker.
<Tip>
Replace `[SUBDOMAIN]` with your unique subdomain, `[YOUR_DOMAIN]` with your website's base URL, and `/docs` with your desired subpath if different.
</Tip>
```javascript
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
if (/^\/docs/.test(urlObject.pathname)) {
// Then Proxy to Mintlify
const DOCS_URL = "[SUBDOMAIN].mintlify.dev";
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, play the regular request
return await fetch(request);
}
}
```
Select **Deploy** and wait for the changes to propagate.
<Propagating />
### Test your Worker
After your code deploys, test your Worker to ensure it routes to your Mintlify docs.
1. Test using the Worker's preview URL: `your-worker.your-subdomain.workers.dev/docs`
2. Verify the Worker routes to your Mintlify docs and your website.
### Add custom domain
1. In your [Cloudflare dashboard](https://dash.cloudflare.com/), navigate to your Worker.
2. Go to **Settings > Domains & Routes > Add > Custom Domain**.
3. Add your domain.
<Tip>
We recommend you add your domain both with and without `www.` prepended.
</Tip>
See [Add a custom domain](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/#add-a-custom-domain) in the Cloudflare documentation for more information.
### Resolve DNS conflicts
If your domain already points to another service, you must remove the existing DNS record. Your Cloudflare Worker must be configured to control all traffic for your domain.
1. Delete the existing DNS record for your domain. See [Delete DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) in the Cloudflare documentation for more information.
2. Return to your Worker and add your custom domain.
## Webflow custom routing
If you use Webflow to host your main site and want to serve Mintlify docs at `/docs` on the same domain, you'll need to configure custom routing through Cloudflare Workers to proxy all non-docs traffic to your main site.
<Warning>
Make sure your main site is set up on a landing page before deploying this Worker, or visitors to your main site will see errors.
</Warning>
1. In Webflow, set up a landing page for your main site like `landing.yoursite.com`. This will be the page that visitors see when they visit your site.
2. Deploy your main site to the landing page. This ensures that your main site remains accessible while you configure the Worker.
3. To avoid conflicts, update any absolute URLs in your main site to be relative.
4. In Cloudflare, select **Edit Code** and add the following script into your Worker's code.
<Tip> Replace `[SUBDOMAIN]` with your unique subdomain, `[YOUR_DOMAIN]` with your website's base URL, `[LANDING_DOMAIN]` with your landing page URL, and `/docs` with your desired subpath if different. </Tip>
```javascript
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
if (/^\/docs/.test(urlObject.pathname)) {
// Proxy to Mintlify
const DOCS_URL = "[SUBDOMAIN].mintlify.dev";
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);
}
}
```
5. Select **Deploy** and wait for the changes to propagate.
<Propagating />