Reverse proxy setup
When you host Fern docs on a subpath like mydomain.com/docs, your infrastructure must proxy requests from that path to Fern’s origin. Subdomain setups (docs.mydomain.com) use a CNAME record instead and don’t require a reverse proxy.
How it works
A working reverse proxy does two things:
- Routes requests from your subpath to Fern’s origin at
app.buildwithfern.com, preserving the original path. Thex-fern-hostheader tells Fern which docs site to serve. - Disables caching of HTML responses so visitors always receive the current deployment.
Every proxied request needs two headers:
Fern sets Cache-Control: public, max-age=0, must-revalidate on HTML responses, which most providers respect by default. If yours overrides origin cache headers or applies its own time-to-live, explicitly disable caching for the proxied path.
Don’t cache HTML responses from Fern. Cached HTML references JavaScript and CSS from older deployments — those files no longer exist, so pages fail to load. Static assets (/_next/static/*) are served directly by Fern’s CDN and don’t pass through your proxy.
Set up your provider
Cloudflare Workers
Create the Worker
Create a Cloudflare Worker that intercepts requests to your docs subpath and proxies them to Fern:
Replace SUBPATH and FERN_HOST with your subpath and bare domain.
Attach the Worker to a route
In the Cloudflare dashboard under Workers Routes, attach the Worker to a route pattern like mydomain.com/docs/*.
Check for conflicting cache rules
The Worker forwards Fern’s Cache-Control header, so caching works automatically. In the Cloudflare dashboard, confirm that no Page Rule or Cache Rule sets “Cache Level: Cache Everything” for /docs* — if one exists, remove it or override it with “Cache Level: Bypass.”
AWS CloudFront
Add a Fern origin
In your CloudFront distribution, go to Origins and create a new origin:
Under Add custom header, add:
Replace mydomain.com with your bare domain (without the subpath).
Create a cache behavior for your docs path
Go to Behaviors and create a new behavior:
AllViewerExceptHostHeader forwards all viewer headers, query strings, and cookies to the origin while letting CloudFront set the Host header to app.buildwithfern.com. This is required — Fern’s origin uses the Host header for routing and rejects requests with an unrecognized host.
Do not use the AllViewer origin request policy. It forwards the viewer’s Host header (your domain) instead of the origin’s, which causes Fern’s origin to return errors or raw React Server Component payloads instead of HTML.
CloudFront ignores CDN-Cache-Control and Surrogate-Control — only the standard Cache-Control header is read. If you use a custom cache policy instead of CachingDisabled, set the default, minimum, and maximum TTL to 0. A non-zero default TTL caches HTML responses regardless of Fern’s Cache-Control: max-age=0 directive, which can cause stale content and errors.
Netlify
Disable rate limiting for the docs path
Fern revalidates your docs site by warming page caches with concurrent requests. Netlify’s traffic rules can interpret this as abusive traffic and block the requests, causing revalidation to fail.
If you have rate limiting enabled under Security > Traffic rules in the Netlify dashboard, add a rule that excludes your docs subpath (/docs/*) from rate limiting.
Check the proxy timeout
Fern’s revalidation endpoint streams a long-running response while warming page caches. Netlify limits proxy rewrite requests to 26 seconds, which can terminate the stream before warming completes on sites with more than a few hundred pages.
If revalidation consistently fails with a “terminated” status, this timeout is the most likely cause. Contact Netlify support to request a timeout increase for your site, or reach out to Fern support for alternative warming options.
Netlify rewrites with status = 200 act as a reverse proxy — the visitor’s browser sees your domain while the content comes from Fern. Netlify respects the origin’s Cache-Control header, so no extra caching configuration is needed.
Vercel
Add a route with a transform
Use a route with a transform rule to rewrite the path and set x-fern-host in one step:
Vercel respects the origin’s Cache-Control header for rewrite destinations, so no extra caching configuration is needed.
Nginx
Nginx doesn’t natively support Brotli decompression. The Accept-Encoding override above prevents HTTP/2 transfer errors caused by Fern’s default Brotli-compressed responses.
Verify your setup
Run these checks against your live subpath:
If content-type is text/x-component instead of text/html, your proxy is forwarding the viewer’s Host header to Fern’s origin. Ensure the Host header sent to the origin is app.buildwithfern.com.
If the age header is present and non-zero, your proxy is serving a cached response. Revisit your provider’s configuration to ensure HTML caching is disabled.