mirror of
https://github.com/mintlify/docs.git
synced 2026-09-14 13:35:46 +08:00
7685f77eea
* docs: apply brand tone and writing style fixes to custom domain pages * docs: capitalize Worker in Cloudflare test heading for consistency --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
192 lines
8.1 KiB
Plaintext
192 lines
8.1 KiB
Plaintext
---
|
|
title: "Deploy at a subpath with Cloudflare Workers"
|
|
sidebarTitle: "Cloudflare"
|
|
description: "Deploy your Mintlify documentation at a subpath on your domain using Cloudflare Workers with step-by-step setup and DNS configuration."
|
|
keywords: ["Cloudflare Workers", "subpath routing", "reverse proxy setup", "Worker configuration"]
|
|
boost: 3
|
|
---
|
|
|
|
import Propagating from "/snippets/custom-subpath-propagating.mdx";
|
|
import SubpathSetupSteps from "/snippets/subpath-setup-steps.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 (managed on or off Cloudflare).
|
|
</Info>
|
|
|
|
## Set your base path
|
|
|
|
<SubpathSetupSteps />
|
|
|
|
The dashboard displays a Cloudflare Worker script with your subdomain, domain, and base path filled in. Use this script in the [Configure routing](#configure-routing) step instead of manually replacing the placeholder values in the example script.
|
|
|
|
## Set up a 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 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
|
|
|
|
In your Cloudflare dashboard, click **Edit Code** and add the script from your [Custom domain setup](https://app.mintlify.com/settings/deployment/custom-domain) page, which has your values filled in, or copy the following example script. See the [Cloudflare documentation](https://developers.cloudflare.com/workers-ai/get-started/dashboard/#development) for more information on editing a Worker.
|
|
|
|
<Tip>
|
|
If you use the example script, 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.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, play the regular request
|
|
return await fetch(request);
|
|
}
|
|
}
|
|
```
|
|
|
|
Click **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>
|
|
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 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, configure custom routing through Cloudflare Workers. The Worker proxies all non-docs traffic to your main site.
|
|
|
|
<Warning>
|
|
Set up your main site on a landing page before deploying this Worker, or visitors to your main site may see errors.
|
|
</Warning>
|
|
|
|
1. 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.
|
|
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, click **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.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);
|
|
}
|
|
}
|
|
```
|
|
5. Click **Deploy** and wait for the changes to propagate.
|
|
|
|
<Propagating />
|