Encited logo
Pricing

How to Integrate Pre-rendering with Cloudflare Workers

Integrate pre-rendering with Cloudflare Workers so crawler requests receive rendered HTML while browser traffic continues to your origin.

This page covers the standard setup for a site you host yourself behind Cloudflare. If your site lives on a site builder or e-commerce platform (Lovable, Base44, Shopify, and others), use the dedicated guide in Hosted platform guides below instead.

Prerequisites

  • An Encited account and API key (Settings → API Keys)
  • A domain added + verified in your Encited dashboard
  • Cloudflare account with Workers enabled
  • Your domain's DNS managed by that Cloudflare account, with the A/CNAME record proxied (orange cloud), since Worker routes only run on traffic that passes through Cloudflare's proxy

Standard setup

1

Create a new Worker

Open Cloudflare dashboard → choose a "Hello World" Worker → Deploy → Edit Code

2

Paste the snippet below into the Worker editor

encited.js
CopyDownload
// encited.js (Cloudflare Worker)
export default {
async fetch(req, env) {
// Only handle public GET navigations
if (req.method !== 'GET') return fetch(req);
// Treat missing/empty Accept and bare '*/*' as HTML so crawler tests
// (curl without -H, default fetch) still route through prerender.
// Asset requests from browsers send specific Accept (e.g. 'text/css,*/*;q=0.1')
// so they won't match.
const accept = (req.headers.get('accept') || '').trim();
const isHtmlRequest = !accept || accept === '*/*' || accept.includes('text/html');
if (!isHtmlRequest) return fetch(req);
const headers = new Headers();
headers.set('x-lovablehtml-api-key', env.LOVABLEHTML_API_KEY);
headers.set('accept', 'text/html');
const forward = [
'accept-language',
'sec-fetch-mode',
'sec-fetch-site',
'sec-fetch-dest',
'sec-fetch-user',
'upgrade-insecure-requests',
'referer',
'user-agent',
];
for (const name of forward) {
const v = req.headers.get(name);
if (v) headers.set(name, v);
}
try {
const r = await fetch(
'https://encited.com/api/prerender/render?url=' + encodeURIComponent(req.url),
{ headers, redirect: 'manual' },
);
// 301 = configured redirect rule matched - forward to client
if (r.status === 301) {
const loc = r.headers.get('location');
if (loc) {
return new Response(null, {
status: 301,
headers: { location: loc, 'cache-control': 'no-store' },
});
}
}
// 304 = not pre-rendered, pass through to origin
if (r.status === 304) {
return fetch(req);
}
if (r.status === 200 && (r.headers.get('content-type') || '').includes('text/html')) {
const responseHeaders = new Headers(r.headers);
for (const name of ['content-encoding', 'content-length', 'transfer-encoding', 'connection', 'keep-alive']) {
responseHeaders.delete(name);
}
responseHeaders.set('content-type', 'text/html; charset=utf-8');
return new Response(r.body, { status: 200, headers: responseHeaders });
}
} catch {
// Prerender unreachable → fall through so visitors still get the site
}
return fetch(req);
},
};
3

Add the API key secret

Under Variables and Secrets, add a secret named LOVABLEHTML_API_KEY or run: wrangler secret put LOVABLEHTML_API_KEY

4

Confirm your DNS record is proxied

Routes need your domain's DNS to be managed in the same Cloudflare account. In DNS → Records, the A or CNAME record for yourdomain.com must show an orange cloud (Proxied), not gray (DNS only). The Worker only runs on traffic that passes through Cloudflare's proxy.

5

Add a route to your Worker

Go to your Worker → Settings → Domains & Routes → Add Route → enter yourdomain.com/*. If your site is reachable on both yourdomain.com and www.yourdomain.com, enter *yourdomain.com/* instead so both are covered.

Hosting on a subdomain? Use blog.yourdomain.com/* for just that subdomain, or *.yourdomain.com/* to cover every subdomain.

6

Set Failure mode

Set to Fail open (proceed) and save. If the Worker ever errors, requests continue straight to your origin instead of failing.

7

Let crawlers through Cloudflare's bot settings

If you use Bot Fight Mode or AI crawler blocking (Security → Bots), allow the crawlers you want pre-rendered. Those protections run before your Worker, so a blocked crawler never reaches it.

8

Deploy the Worker

It can take a couple of minutes to start working.

How to Test

  1. Call the render API directly and verify x-lovablehtml-render-cache: hit | miss
  2. Hit your site as a crawler and verify the response carries x-lovablehtml-render-cache. That header is what proves the Worker served rendered HTML
  3. Verify a normal browser request falls through to your existing origin
bash
CopyDownload
# 1) Call the Encited render API directly
curl -sS -D - -o /dev/null \
-H "x-lovablehtml-api-key: <API_KEY>" \
-H "Accept: text/html" \
"https://encited.com/api/prerender/render?url=https%3A%2F%2Fyour-domain.com%2Fyour-page"
# Look for:
# - HTTP/1.1 200
# - x-lovablehtml-render-cache: hit | miss
# - x-lovablehtml-snapshot-key: ...
bash
CopyDownload
# 2) Hit your site with an HTML Accept header
curl -sS -D - -o /dev/null \
-H "Accept: text/html" \
-A "Googlebot" \
"https://your-domain.com/your-page"
# Look for:
# - HTTP/1.1 200
# - x-lovablehtml-render-cache: hit | miss
#
# A plain 200 with content-type: text/html is what your origin returns
# too. The x-lovablehtml-render-cache header proves the Worker served
# rendered HTML.
bash
CopyDownload
# 3) Browser passthrough (Encited returns 304; the Worker serves your origin)
curl -sS -D - -o /dev/null \
-A "Mozilla/5.0" \
"https://your-domain.com/your-page"
# Look for:
# - no x-lovablehtml-* headers (the response came from your origin)

Best Practices

  • Keep secrets out of git: Store keys in your platform's secret manager or env vars; rotate/revoke when compromised.
  • Don't proxy static assets: Only call Encited for HTML document requests. Always pass through JS/CSS/images/fonts.
  • Handle 304 passthrough: 304 means prerendering doesn't apply; fall back to your origin. If you get a 301 instead, a redirect rule matched; forward its Location header to the client.
  • Invalidate after content changes: Use the cache invalidation endpoints (optionally with prewarm) after deploys or CMS updates.

Hosted platform guides

Hosting on a site builder or e-commerce platform instead? Each guide below walks the Cloudflare setup for that platform end to end:

Site builders through Cloudflare

Keep Cloudflare in front of your custom domain with a Worker that serves crawlers pre-rendered HTML and forwards visitors to your hosted project.

E-commerce platforms through Cloudflare

Your DNS keeps pointing at the platform. A Worker route in your Cloudflare zone intercepts crawler requests before they reach the store.

Need help? Check the full API reference for prerender, cache, and analytics endpoint docs, or jump directly to Analytics API, or contact us if you run into issues.

Avatar
How can we help?
Get instant answers to your questions or leave a message for an engineer will reach out
Ask AI about Encited
See our docs
Contact support
Leave a message
We'll get back to you soon
Avatar
Ask AI about Encited
Team is also here to help
Thinking
Preview
Drop an image to attach
Powered by ReplyMaven