Documentation menu

Cloudflare Worker & edge

A fetch-handler factory for web-standard edge runtimes (@rebilder/gateway/edge): a complete worker in five lines, with origin pass-through included.

From nothing to deployed

Four commands and one file of your own content. This puts the gateway in front of a site you already have, on a domain already on Cloudflare, on any plan including Free.

Scaffold and install
npm create cloudflare@latest my-rebilder-gateway -- --type=hello-world --ts
cd my-rebilder-gateway
npm install @rebilder/gateway

Then replace src/index.ts with the worker below, add your pages, and point wrangler.jsonc at your zone:

wrangler.jsonc: the only required edit
"routes": [
  { "pattern": "example.com/*", "zone_name": "example.com" },
  { "pattern": "www.example.com/*", "zone_name": "example.com" }
]
Ship it
npx wrangler login
npx wrangler deploy

Verify with curl -sI https://example.com/your-page -H "Accept: text/markdown": seeing content-type: text/markdown and x-rebilder-path: markdown means you are live. npx wrangler tail streams the events.

Hand this to your coding agent

If you would rather not wire it by hand, paste this into Claude Code, Cursor, or whatever you build with. It is written to be unambiguous about the parts that are easy to get wrong.

Prompt
Set up a Cloudflare Worker that puts @rebilder/gateway in front of my site.

WHAT IT DOES
The Worker sits on a route in front of the origin. When an AI agent requests a
URL with `Accept: text/markdown` AND that URL is one I have described, it
answers with clean markdown rendered from typed data. Everything else — humans,
Googlebot, URLs I have not described — is forwarded to the origin unchanged.

STEPS
1. Scaffold a TypeScript Worker and add the dependency:
     npm create cloudflare@latest my-rebilder-gateway -- --type=hello-world --ts
     cd my-rebilder-gateway && npm install @rebilder/gateway
2. Read node_modules/@rebilder/gateway/README.md before writing anything. Do
   not work from memory of this prompt.
3. Create `src/content.ts`: a `Map<string, DocumentSource>` keyed by pathname,
   and a `Map<string, CollectionSource>` for index pages. Ask me for the real
   values — see the rules below.
4. Create `src/gateway-config.ts` exporting a `GatewayConfig` whose `document`
   and `collection` resolvers are `Map.get` on the normalised pathname, plus a
   pure synchronous `match` router returning 'document', 'collection', or null.
5. Make `src/index.ts`:
     import { createGatewayFetchHandler } from '@rebilder/gateway/edge'
     export default { fetch: createGatewayFetchHandler(gatewayConfig) }
6. In wrangler.jsonc, set `routes` to my zone. Ask me for the hostname.

RULES — these are not style preferences
- Never invent a substantive value. Prices, opening hours, turnaround times,
  what a service includes, whether booking is required — all of it comes from
  me. If you do not have a value, ask. Do not write a plausible-looking
  placeholder into content.ts; it will ship, and an agent will quote it.
- Money is in MINOR UNITS. { amount: 180, currency: 'GBP' } is £1.80, not £180.
  Write a helper that takes major units and multiply by 100 in one place.
  Zero-decimal currencies (JPY, KRW, ISK) take whole units — do not multiply.
- Never fetch anything on the markdown path. The whole point is that a described
  page is answered from the Worker bundle with no origin round-trip. If you
  find yourself adding a fetch inside a resolver, stop and ask me.
- A resolver returns null when the URL is not that kind of page. null means
  "forward to the origin", which is always a safe answer.
- Forward the origin's response as-is. Do not rewrite its status, do not turn a
  502 into a friendly page, do not follow its redirects inside the Worker.
- Do not change the origin. This is additive, and `wrangler delete` must be a
  complete rollback.

WHEN YOU ARE DONE
Tell me which pathnames now serve markdown and which pages I still need to
describe. Then verify against the deployed site — one real URL of each kind:

  curl -sI https://MY-DOMAIN/PATH -H 'Accept: text/markdown'   # expect text/markdown
  curl -sI https://MY-DOMAIN/PATH                              # expect my normal HTML
  npx rebilder check https://MY-DOMAIN/PATH                    # grades the page

If you cannot answer "which URLs now serve markdown", the setup is not done.

A complete worker

The adapter needs no Cloudflare imports: (req: Request) => Promise<Response> is the whole contract, and export default { fetch } satisfies a CF Worker’s fetch handler without any workers-types coupling. Deploy it on a route in front of the store:

worker.ts
// worker.ts — deploy on a route in front of the store, e.g. store.example.com/*
import { createGatewayFetchHandler } from '@rebilder/gateway/edge'
import { gatewayConfig } from './gateway-config'

export default { fetch: createGatewayFetchHandler(gatewayConfig) }

That is a complete worker: agent traffic with a matching source gets the standard markdown response; everything else is fetch(req)-ed to the origin unchanged, which is the standard CF Worker reverse-proxy pattern, so browsers and crawlers get the canonical HTML exactly as if the worker weren’t there.

Serving the non-markdown path yourself

Pass options.fallback: (req) => Response | Promise<Response> to serve the non-markdown path yourself instead of proxying, which is useful for workers that are not fronting an origin, or for tests.

Latency note

A gateway-internal error is contained like every other failure: the request falls through to fallback/origin, never a 500.

Vercel Edge & other WinterCG runtimes

The same plain fetch handler works on Vercel Edge Functions (or any WinterCG runtime): export it as the handler. Use options.fallback there, since Vercel Edge functions don’t sit in front of an origin the way a route-mounted CF Worker does. In Next.js projects, prefer the ./next adapter, which plugs into middleware natively.