@astrojs/cloudflare. No adapter switch, no Redis, no Node server./app on a Webflow site. Direct Cloudflare gives you the root of a domain you own.wrangler deploy, no GitHub connection required. Continuous deployment is optional via a GitHub Action if you want it.npm on your machine.npx. The repo's package.json already lists it as a devDep.cd neuromast
npm install
npx wrangler login
Opens a browser for OAuth. Stores the token in your user profile; persists across terminals.
npx wrangler kv namespace create QUEUE
Wrangler prints a snippet to paste into wrangler.json:
"kv_namespaces": [
{ "binding": "QUEUE", "id": "<generated-id>" }
]
Paste it into wrangler.json at the top level (next to compatibility_date). The binding name must be QUEUE — that's what the storage factory auto-detects.
Wrangler stores these encrypted with the project; they're not in the repo and don't ship in the bundle:
npx wrangler secret put POLL_TOKEN
npx wrangler secret put SHARED_SECRET # optional, for ?key= fallback
npx wrangler secret put HOOK_SCHEME_GITHUB # e.g. "github"
npx wrangler secret put HOOK_SECRET_GITHUB # your webhook secret
Each one prompts for the value. Repeat for every signed source.
npx wrangler deploy
Wrangler builds the Astro bundle, packages it as a Worker, and uploads it. You'll get a https://neuromast.<your-account>.workers.dev URL in the output.
For a custom domain: dashboard → Workers & Pages → your worker → Settings → Domains & Routes → Add Custom Domain. Point a DNS record at Cloudflare first if the domain isn't already on your account.
export AXOL_CLOUD_URL=https://neuromast.<your-account>.workers.dev
export POLL_TOKEN='the-bearer-you-set'
export SHARED_SECRET='the-shared-key-you-set'
curl -X POST "$AXOL_CLOUD_URL/app/api/hooks/smoke?key=$SHARED_SECRET" \
-H 'content-type: application/json' \
-d '{"title":"hello","body":"from cloudflare"}'
curl -H "Authorization: Bearer $POLL_TOKEN" "$AXOL_CLOUD_URL/app/api/pull"
Expect 204 on the POST, JSON with your item on the GET. Routes live under /app/api/… because the Astro config has base: '/app' — remove it if you want the routes at the domain root.
AXOL_CLOUD_URL="$AXOL_CLOUD_URL" \
AXOL_POLL_TOKEN="$POLL_TOKEN" \
./lateral-line/install.sh
npx wrangler deploy
To automate on git push, use Cloudflare's official GitHub Action (cloudflare/wrangler-action). One workflow file, one CLOUDFLARE_API_TOKEN secret in the repo. Optional — the manual CLI path is equally valid for a solo user.
wrangler secret put <NAME> overwrites the existing value. The next request uses the new secret automatically (Workers don't need an explicit restart).
Free tier: 100 k requests/day, 1 GB KV storage, 30 MB bundle size. Axol's traffic pattern sits well under this; a paid plan only matters if you're hosting many users or running heavy integrations.
wrangler deploy fails with "Invalid binding QUEUE"
The KV namespace isn't declared in wrangler.json, or its id doesn't match a namespace on your account. Re-run wrangler kv namespace create QUEUE and paste the output.
401 on every request
Secrets aren't set yet or haven't propagated. Confirm with wrangler secret list, then try again.
Free-tier Workers cap at 1 MB gzipped (10 MB paid). The default build sits around 950 KB — you're fine. If it creeps past 1 MB, review npm ls for accidental dependencies.
DNS takes a minute to propagate; Cloudflare also needs to attach a route for the worker. Dashboard → Workers & Pages → your worker → Triggers → Routes.