What you'll build

In this final part you'll deploy the bot to Cloudflare Workers. Workers run at Cloudflare's edge network — over 300 locations worldwide — with no server to manage, automatic scaling, and a free tier of 100,000 requests per day.

Because Workers use a different runtime from Node.js, this part walks you through adapting the bot to run without Express, and replacing the in-memory session Map with Workers KV (a global key-value store).

Set up Wrangler

Wrangler is the Cloudflare Workers CLI:

npm install -g wrangler
wrangler login

In your project root, create wrangler.toml:

name = "quickbites-bot"
main = "src/worker.ts"
compatibility_date = "2024-09-23"

[vars]
TWILIO_WHATSAPP_NUMBER = "whatsapp:+14155238886"

[[kv_namespaces]]
binding = "SESSIONS"
id = "your-kv-namespace-id"

Create the KV namespace:

wrangler kv:namespace create SESSIONS

Wrangler prints the namespace ID — copy it into wrangler.toml.

Add secrets to Workers

Workers Secrets are environment variables that are never visible in plaintext:

wrangler secret put TWILIO_ACCOUNT_SID
wrangler secret put TWILIO_AUTH_TOKEN
wrangler secret put PAYSTACK_SECRET_KEY

Adapt the session manager for KV

BlocWeave prompt

Create src/session-kv.ts to replace src/bot/session.ts for the Cloudflare Worker runtime. The Worker environment receives a SESSIONS KV binding via env. KV is async — reads and writes use await. Export a SessionStore class with constructor(kv: KVNamespace): - async get(from: string): Promise — await kv.get(from, "json"); return result ?? { step: "main", cart: [] } - async set(from: string, state: SessionState): Promise — await kv.put(from, JSON.stringify(state), { expirationTtl: 3600 }) — sessions expire after 1 hour of inactivity - async addToCart(from: string, item: MenuItem): Promise — get session, update cart, set session - async clearCart(from: string): Promise — get session, set cart to [], set session - async cartTotal(from: string): Promise - async formatCart(from: string): Promise Keep the same logic as session.ts but all methods are async and use KV instead of a Map.

Build the Worker entry point

BlocWeave prompt

Create src/worker.ts — the Cloudflare Worker entry point. A Cloudflare Worker exports a default object with a fetch(request, env) method. There is no Express — use the standard Request/Response Web API. Handle POST /webhook: parse the request body as URL-encoded form data (Twilio sends application/x-www-form-urlencoded). Extract Body, From, To. Create a SessionStore(env.SESSIONS). Run the same routing logic as handler.ts but using await for all session calls. Send the Twilio reply using fetch() with a Basic auth header (base64(accountSid:authToken)) instead of the Twilio SDK (SDK doesn't work in Workers). Handle POST /webhook/paystack: verify the Paystack signature using the SubtleCrypto API (available in Workers: await crypto.subtle.importKey / crypto.subtle.sign). Parse the event, send confirmation via Twilio fetch. Handle GET /health: return Response.json({ status: "ok" }). For all other paths: return new Response("Not found", { status: 404 }). Env type: { TWILIO_ACCOUNT_SID: string; TWILIO_AUTH_TOKEN: string; TWILIO_WHATSAPP_NUMBER: string; PAYSTACK_SECRET_KEY: string; SESSIONS: KVNamespace }

Deploy to Cloudflare

wrangler deploy

Wrangler compiles your TypeScript, uploads to Cloudflare, and prints your Worker URL:

https://quickbites-bot.your-subdomain.workers.dev

Update Twilio and Paystack

In Twilio sandbox settings, update the webhook URL:

https://quickbites-bot.your-subdomain.workers.dev/webhook

In Paystack webhooks settings, update:

https://quickbites-bot.your-subdomain.workers.dev/webhook/paystack

Test the live bot

On your phone, send menu to the Twilio sandbox number. The message goes to Twilio → your Worker → back to WhatsApp. Navigate the menu, add an item, type pay, and complete a test payment. You should get the confirmation message back on WhatsApp.

Free tier: Cloudflare Workers free tier gives 100,000 requests/day and 10ms CPU time per request (plenty for a chat bot). Workers KV gives 100,000 reads/day and 1,000 writes/day. For a small business bot this is more than sufficient. Paid plans are $5/month if you need more.

What you've built

Over this four-part series you've built a full WhatsApp ordering bot:

You can extend this by adding order history (store orders in a D1 database), an admin notification when a new order comes in, or a daily menu broadcast to subscribers.