Skip to content

Repository files navigation

Ooky Worker Template

Deployable Cloudflare Worker for the BYO Cloudflare integration tier. Customers deploy this to their own Cloudflare account, paste their Ooky API key, and traffic for their domain is intercepted at the edge - no DNS change to a vendor zone.

This is a template repo (this directory pushed to https://github.com/cloudweld/worker-template).

Most customers never need this. The Ooky dashboard deploys this Worker into your Cloudflare account for you: you paste one pre-scoped API token and Ooky uploads the script, sets the OOKY_API_KEY secret, and binds your route. Use the manual steps below only if you want to self-manage the deploy, or your Cloudflare account won't let you mint an API token.

The dashboard uploads a bundled build of src/, produced by npm run bundle and committed at backend/src/assets/worker-bundle/. Change anything in src/ and you must re-run that command and commit the result, or __tests__/bundleParity.test.mjs fails.


⚠️ STEP 1 (REQUIRED): wire the routes - do this BEFORE anything else

A Worker only intercepts your site if it's bound to your domain's routes. A plain wrangler deploy (or the one-click button) with the routes block still commented out deploys the Worker to a *.workers.dev URL bound to zero of your routes - it never sees real traffic. The deploy "succeeds" and the Ooky dashboard may even flip to "Connected", but every AI manifest endpoint and all bot analytics are silently dead.

You must edit wrangler.toml first:

  1. Uncomment the routes block and set it to your domain:
    routes = [
      { pattern = "your-domain.com/*", zone_name = "your-domain.com" }
    ]
  2. Set OOKY_DOMAIN in [vars] to your registered Ooky domain (replace the YOUR_DOMAIN placeholder - the Worker treats the literal placeholder as unconfigured and returns a loud error instead of silently failing).
  3. Set the top-level Worker name to a unique value for this hostname, with a short random or hash suffix, for example ooky-example-com-a13f09c2. Never reuse the old account-global ooky-worker name across domains: a later deploy would replace the code and secrets behind every route that points to it. The runtime also verifies the request hostname and passes a mismatched legacy route straight through to its origin.

The one-click "Deploy to Cloudflare" button is NOT sufficient on its own. It scaffolds the Worker but cannot wire your routes for you. After clicking it you still have to do STEP 1 above, or the integration is a no-op.

After deploying, run the self-diagnostic to confirm everything is wired:

curl -s https://your-domain.com/__ooky/health | jq

It reports whether the Worker is bound to your domain, whether OOKY_DOMAIN and OOKY_API_KEY are set, and exactly what to fix if not. If you hit it on the *.workers.dev URL, it will tell you the routes aren't wired.


Manual deploy

git clone https://github.com/cloudweld/worker-template.git
cd worker-template
npm install

# STEP 1 (REQUIRED): set OOKY_DOMAIN, choose a unique per-host `name`, and
# uncomment the `routes` block.
$EDITOR wrangler.toml

# Set the Bearer token (from your Ooky dashboard → Integrations → Worker)
npx wrangler secret put OOKY_API_KEY

# (Optional) Create a KV namespace for cross-request bot-registry caching
npx wrangler kv namespace create OOKY_BOT_CACHE
# Paste the printed `id` into wrangler.toml under [[kv_namespaces]]

npx wrangler deploy --config wrangler.toml

One-click deploy

Deploy to Cloudflare

The button scaffolds the Worker into your account but does not wire your routes - you must still complete STEP 1 (uncomment routes, set OOKY_DOMAIN) or the Worker intercepts nothing.

What the Worker does

For each request that reaches the bound route, the template runs this decision flow:

  1. Loads the bot-UA registry from /api/public/bots. By default this is cached in memory per isolate (each new isolate refetches on its first request). If you bind the optional OOKY_BOT_CACHE KV namespace, it's also cached in KV for an hour so isolates share it.
  2. Checks the User-Agent against the registry. If it's a known AI bot, attempts a non-blocking bot event to Ooky's ingest endpoint with your per-domain Bearer token (and the request's cf.country for geo). This delivery is best-effort, so the resulting event feed is not a complete request log.
  3. For non-bot traffic, detects humans arriving from an AI platform (ChatGPT/Perplexity/Claude/…) via the Referer header or a utm_source param, and attempts a non-blocking ai_referral event so the dashboard's attribution lands.
  4. If the path matches one of the well-known AI URLs, serves the manifest from Ooky's public CDN:
    • /llms.txt
    • /llms-full.txt
    • /agents.md
    • /.well-known/ai-manifest.json (and /ai-manifest.json)
    • /.well-known/mcp and /mcp (full MCP JSON-RPC, see below)
  5. If the request is a bot on a content page (a GET that wants HTML, not an asset), the Worker fetches the latest published, parity-gated distilled HTML for that path from Ooky's bearer-authed per-page API and serves it in place of your origin markup. When nothing is published the API returns 204 and the request falls through to your origin. Humans always get your real page.
  6. Otherwise, the request passes through to your origin unchanged.

MCP support

/mcp and /.well-known/mcp speak the MCP JSON-RPC 2.0 protocol that real clients (Claude, the MCP Inspector, ChatGPT connectors) use:

  • GET returns the static descriptor from the public CDN.
  • POST handles initialize, tools/list, and tools/call for the get_brand_info tool, plus the legacy { tool, arguments } shape. OPTIONS returns CORS preflight headers. This mirrors @ooky/sdk's MCP behaviour; the server identifies itself as ooky-<your-domain>.

This tier exposes only get_brand_info (product/feed tools require feed data this tier doesn't have).

What this tier does - and does NOT do (vs Full-DNS)

The BYO-Worker tier intercepts bots, fires analytics, and serves the well-known AI artifacts. It is intentionally simpler than the Full-DNS tier (where you point your domain's DNS at Ooky):

Capability BYO Worker (this) Full-DNS
Bot detection + AI-Sessions analytics
AI-referral attribution (human from ChatGPT/…)
Serve /llms.txt, /llms-full.txt, /agents.md, AI manifest
MCP JSON-RPC endpoint (get_brand_info) ✅ (+ product tools)
Distilled / cleaned-HTML served to bots on normal pages ✅ (when published)
JSON-LD injection into your human HTML
Content negotiation rewrite of your human HTML
Reverse-DNS / IP-CIDR bot verification ❌ (UA-only)

Important: cleaned-HTML serving on this tier starts once the integration is installed and an eligible page artifact is published. It is fetched from Ooky's per-page API (a customer-deployed Worker has no R2 binding, so it reads the artifact over HTTP rather than from the edge store the managed Worker uses). When a page has nothing published, a bot hitting a normal page gets your origin's HTML unchanged. JSON-LD injection into human pages and content-negotiation rewrites remain Full-DNS differentiators; they require Ooky inline in front of every request.

Resilience

  • Timeouts: every upstream fetch (manifest serve, event ingest, bot-registry refresh) carries an AbortSignal deadline so a hung Ooky API never stalls your site.
  • Ownership-safe revalidation: manifest and per-page artifact fetches bypass the Workers Cache API on every request. A hostname can move between Ooky workspaces, so the former owner's body is never a stale availability fallback.
  • No artifact caching: success and error responses are private and no-store; a pre-publish 404 or transient 5xx cannot stick after recovery.
  • Ownership proof: every successful manifest or page artifact must include a valid hostname claim ID, generation, exact edge namespace, and the fresh request nonce. Fetches carry the domain-scoped Bearer key; revoked or former- owner installs and replayed intermediary 200s fail closed.

Configuration

Variable Where set Required Description
routes wrangler.toml Yes The domain/route the Worker binds to. Without it the Worker intercepts nothing (see STEP 1).
OOKY_DOMAIN wrangler.toml [vars] Yes The domain you registered in the Ooky dashboard. Must match the verified domain. The literal YOUR_DOMAIN placeholder is treated as unconfigured.
OOKY_API_KEY wrangler secret put Yes Per-domain Bearer token (ooky_sk_*) from the Ooky dashboard.
OOKY_API_BASE wrangler.toml [vars] No Defaults to https://api.ooky.ai/api. Override only if you self-host Ooky.
OOKY_BOT_CACHE KV binding No Optional. Caches the bot registry in KV across requests/isolates. Without it, each new isolate refetches on its first request (in-memory only).
ORIGIN_SERVICE Service binding No Required when replacing an existing site Worker's route. A site Worker on a Custom Domain can use native passthrough. See below.

If your site is already served by a Worker

Cloudflare distinguishes a Worker on a Custom Domain from a Worker on a route. Native passthrough (fetch(request)) reaches a normal server or a site Worker on a Custom Domain. It cannot invoke another same-zone route Worker.

A route pattern maps to exactly one script. Replacing an existing site's route requires binding that original script so it continues to serve the site. Do not overwrite overlapping wildcard or path routes without reviewing their behavior; the Ooky guided setup blocks these ambiguous configurations.

Bind your site's Worker instead:

# wrangler.toml
[[services]]
binding = "ORIGIN_SERVICE"
service = "your-site-worker-name"

Passthrough now invokes the bound Worker. Verify with /__ooky/health?check_origin=1: origin.reachable must be true, and origin.mode is service for a binding or fetch for native passthrough. The probe performs a sanitized homepage request, cancels its body, and times out after eight seconds. The regular health endpoint only checks configuration. A failing service returns 502 to visitors without replaying their request into a different origin.

Cloudflare documents these distinct paths in Routes and Custom Domains.

Verifying the deploy

# Self-diagnostic - checks routes/domain/key wiring and tells you what's wrong:
curl -s 'https://your-domain.com/__ooky/health?check_origin=1' | jq

# Bot path + a manifest path:
curl -s https://your-domain.com/llms.txt | head
curl -I -H "User-Agent: GPTBot/1.0" https://your-domain.com/

Within ~30 seconds the integration in your Ooky dashboard should flip to "Connected" and the AI Sessions tab should show the event.

Troubleshooting

Symptom Likely cause
Whole site returns HTTP 522 right after deploying this Worker An existing site Worker route may have been replaced without a service binding, or the server is unreachable. Check origin in the health probe; bind the original route Worker when required. Custom Domain Workers can use native passthrough.
/llms.txt returns origin's response Worker route not bound to your domain. Complete STEP 1 (uncomment routes). Run /__ooky/health to confirm.
/__ooky/health reports served_on_workers_dev: true You're hitting the *.workers.dev URL - the routes block isn't wired.
Manifest endpoint returns a loud 500 about YOUR_DOMAIN OOKY_DOMAIN is still the placeholder. Set it in wrangler.toml and redeploy.
Manifest endpoint returns 404 No published manifest yet. Publish from the Ooky dashboard's Builder.
Manifest endpoint returns 401 OOKY_API_KEY is missing, revoked, or belongs to a different/currently transferred hostname. Install the current domain key.
[ooky] ingest responded 401 in wrangler tail OOKY_API_KEY secret missing or wrong. Re-run wrangler secret put OOKY_API_KEY.
Bot events not appearing Check wrangler tail to confirm the Worker is being invoked and watch for [ooky] ingest warnings.

Development

npm install
npm test                       # vitest unit tests
npx wrangler deploy --config wrangler.toml --dry-run  # validate without deploying

Changelog

0.3.0

Adds an explicit origin readiness probe at /__ooky/health?check_origin=1. Guided setup can distinguish working routes from a configured Worker whose origin fails. Failed origin services return a controlled 502 without replaying streamed mutations. Setup guidance now distinguishes Custom Domains from routes.

0.2.0

Adds the optional ORIGIN_SERVICE service binding for sites that have no origin server because the site is itself a Worker (Workers Static Assets, Pages). All three origin-passthrough paths now go Worker-to-Worker when it is bound, instead of dialing an origin that does not exist and returning 522 on every request. /__ooky/health reports origin_service_bound. Unbound, behavior is unchanged. TEMPLATE_VERSION = "0.2.0".

0.1.1

Security release: ownership-sensitive manifest and page artifacts now bypass the Workers Cache API, are never stale-served from isolate memory, and return private no-store responses. TEMPLATE_VERSION = "0.1.1".

0.1.0

Initial release of the BYO-Worker template (TEMPLATE_VERSION = "0.1.0").

  • Bot detection against the Ooky UA registry (/api/public/bots), cached in-memory per isolate and optionally in KV (OOKY_BOT_CACHE).
  • Manifest serving of the well-known AI URLs (/llms.txt, /llms-full.txt, /agents.md, /.well-known/ai-manifest.json, /ai-manifest.json) from Ooky's public CDN.
  • Cleaned-HTML serving to detected bots on content pages when an artifact is published, fetched from Ooky's bearer-authed per-page API.
  • Event logging: non-blocking bot events and ai_referral events fired to Ooky's ingest endpoint with the per-domain Bearer token.
  • MCP endpoint (/mcp, /.well-known/mcp): JSON-RPC 2.0 (initialize, tools/list, tools/call for get_brand_info) plus the legacy Ooky shape.
  • Health endpoint (/__ooky/health): self-diagnostic that reports route, domain, and key wiring and flags the *.workers.dev no-op trap.
  • Stale-serve resilience: timeouts on every upstream fetch, last-good manifest served through a transient 5xx/timeout, and no caching of error responses.

The compatibility_date in wrangler.toml is pinned to 2026-04-01 so the Workers runtime behaviour stays fixed for this release; bump it deliberately when adopting newer runtime semantics.

License

MIT.

About

▎ Deployable Cloudflare Worker for the Ooky BYO-Cloudflare integration — serve AI brand intelligence and capture AI-bot analytics at your own edge. Deploy to your Cloudflare account; bring your own Ooky API key.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages