Every command, every Cloudflare dashboard click, every secret in order. Check off boxes as you go — your progress saves locally to the browser so you can close the tab and resume. Each step has rollback notes if it goes sideways.
If you don't have an account, sign up at cloudflare.com. Free tier is fine for v1.0 launch (we're well under all the rate limits).
dash.cloudflare.comIf 613parts.ca isn't already in your sites list, you need to add it and switch nameservers at your registrar. This is the longest gate — DNS propagation can take 1–24 hours.
Cloudflare will scan existing DNS records and import them. Then it'll show you 2 nameservers (something like jonas.ns.cloudflare.com and kate.ns.cloudflare.com).
Log into wherever 613parts.ca is registered (GoDaddy, Namecheap, Domains.ca, etc.). Find DNS / nameserver settings. Replace whatever's there with the 2 Cloudflare nameservers.
Wait for propagation. Cloudflare emails you when active.
613parts.ca appears in your Cloudflare sites list with status "Active"dig 613parts.ca NS +short returns the Cloudflare nameservers (test from terminal)You need the repo cloned locally and a terminal open in the worker/ subdirectory.
cd /path/to/613parts/worker node --version # v20.x.x or higher ls # should show wrangler.toml, package.json, src/
node is too oldnvm install 20 (if you have nvm) or download from nodejs.org.
From the worker/ directory:
npx wrangler login
What happens:
Successfully logged in.npx wrangler whoami
You are logged in with a Cloudflare API Token, associated with the email your@email.com. 👋 You are logged in with the email associated with the Cloudflare account: Your Account (acct-id)
wrangler login hangs or failsnpx wrangler logout first then re-login.
Multiple accounts? Set the right one with export CLOUDFLARE_ACCOUNT_ID=xxx after login.
Catalog data, AS400 invoice imports, computed driver routes, delivery events — all live in this bucket.
npx wrangler r2 bucket create 613parts-catalog
Creating bucket '613parts-catalog'... Created bucket '613parts-catalog'.
npx wrangler r2 bucket list shows the bucketKV caches geocoder results so we don't re-bill Google Maps for repeat customer addresses.
npx wrangler kv:namespace create SEARCH_CACHE
🌀 Creating namespace with title "613parts-bot-worker-SEARCH_CACHE" ✨ Success! Add the following to your configuration file: [[kv_namespaces]] binding = "SEARCH_CACHE" id = "a1b2c3d4e5f67890abcdef1234567890"
id valueOpen worker/wrangler.toml and replace both occurrences of "REPLACE_WITH_KV_NAMESPACE_ID" with that id:
# Top-level (used by `wrangler dev`) [[kv_namespaces]] binding = "SEARCH_CACHE" id = "a1b2c3d4e5f67890abcdef1234567890" # Production (used by `wrangler deploy --env production`) [[env.production.kv_namespaces]] binding = "SEARCH_CACHE" id = "a1b2c3d4e5f67890abcdef1234567890"
grep -c REPLACE_WITH_KV_NAMESPACE_ID worker/wrangler.toml returns 0grep -c "$KV_ID" worker/wrangler.toml returns 2 (both top-level and env.production)npx wrangler kv:namespace delete --namespace-id=<id>. Keep just one and update wrangler.toml.
Two are required for the worker to deploy and run; the rest enable specific features.
# Generate a strong secret first openssl rand -hex 32 # copy the output # Then set it npx wrangler secret put JWT_SECRET --env production # prompts: Enter a secret value: paste-the-hex-string
From dashboard.stripe.com → Developers → API keys. Start with the test key (sk_test_*). Swap for live (sk_live_*) when ready to take real money.
npx wrangler secret put STRIPE_SECRET --env production
# Generate, then set
openssl rand -hex 16
npx wrangler secret put CRON_TRIGGER_TOKEN --env production
#ops-quotesIn Slack: create a new app at api.slack.com/apps → Incoming Webhooks → activate → add to #ops-quotes channel → copy webhook URL.
npx wrangler secret put SLACK_WEBHOOK_URL --env production
From console.cloud.google.com → create project → enable Geocoding API → Credentials → create API key → restrict to Geocoding API only (good hygiene).
npx wrangler secret put GOOGLE_MAPS_API_KEY --env production
| POSITRACE_API_URL | Live truck GPS (falls back to phone GPS without) |
| POSITRACE_API_KEY | Pro-tier API token from PosiTrace support |
| POSITRACE_VEHICLES | Format: VEHICLE_4567:belleville,VEHICLE_8901:kingston |
GEOCODE_STUB in production
That env var is for local dev only. If it leaks into prod, every address gets fake coordinates and routes break.
npx wrangler secret list --env production
JWT_SECRETSTRIPE_SECRETCRON_TRIGGER_TOKEN (recommended)SLACK_WEBHOOK_URL (recommended)GOOGLE_MAPS_API_KEY (recommended)wrangler secret put command again with the correct value — it overwrites. To delete: wrangler secret delete SECRET_NAME --env production.
From worker/ directory:
npm install # first time only npm run typecheck # should pass cleanly (0 errors) npm run test:unit # 49 tests passing npx wrangler deploy --env production
Total Upload: ~250 KiB / gzip: ~80 KiB Uploaded 613parts-bot-worker (2.1 sec) Published 613parts-bot-worker (3.4 sec) bot.613parts.ca (custom domain) Current Deployment ID: a1b2c3d4-...
curl https://613parts-bot-worker.your-account.workers.dev/health
okworker/wrangler.toml and verify both KV id fields are set to a real namespace ID, not REPLACE_WITH_KV_NAMESPACE_ID.
npx wrangler login. If you have multiple accounts, ensure the right one is active.
The worker is up at the workers.dev URL. Now route the production custom domain to it.
OR via the worker's settings:
| Field | Value |
|---|---|
| Domain | bot.613parts.ca |
| Environment | production |
Cloudflare auto-creates the DNS record + provisions an SSL cert. Takes ~30 sec.
curl https://bot.613parts.ca/health
okOne project per app. From repo root:
cd ../driver-app npx wrangler pages project create 613parts-driver-app cd ../dispatch-app npx wrangler pages project create 613parts-dispatch-app
main (or whatever your default branch is).
613parts-driver-app.pages.devcd driver-app
npm install
npm run build # NOT build:preview — want real API
npx wrangler pages deploy dist --project-name=613parts-driver-app
dist/ folder includes the _redirects file we shipped (SPA routing) and the PWA service worker. Both deploy automatically.
https://abc123.613parts-driver-app.pages.dev)/login path doesn't 404 (proves _redirects works)cd ../dispatch-app npm install npm run build npx wrangler pages deploy dist --project-name=613parts-dispatch-app
/dashboard path doesn't 404Each Pages project gets its own custom domain. Same flow as worker (Step 6) but on Pages.
Enter: drive.613parts.ca
Enter: dispatch.613parts.ca
Cloudflare provisions DNS + SSL in ~60 seconds for each.
https://drive.613parts.ca loads driver login (with valid SSL)https://dispatch.613parts.ca loads dispatch login (with valid SSL)curl https://bot.613parts.ca/health
okcurl -X POST https://bot.613parts.ca/api/v1/er-search \
-H 'content-type: application/json' \
-d '{"cf_query":"oil filter"}'
"messages" array (empty catalog says "couldn't find a match")curl -I https://drive.613parts.ca
HTTP/2 200 with content-type: text/htmlcurl -I https://dispatch.613parts.ca
HTTP/2 200curl -X POST https://bot.613parts.ca/cron/run \
-H "authorization: Bearer $CRON_TRIGGER_TOKEN"
cron triggered (status 202)#ops-quotes channel receives a notification within ~30 secThis is a separate clicking-through-ManyChat task. Worker URLs are already production-correct (bot.613parts.ca) so the External Request bodies in the guide work as-is.
Open the flow guide:
That doc has 12 sub-steps: 25 Custom Fields, 4 keyword triggers, 5 flows, postback dispatcher, smart filter for live-chat. Plan ~90 min uninterrupted.
npx wrangler tail --env production
Useful when something breaks in production and you need to see what's happening in real-time.
npx wrangler deployments list --env production # Pick a previous deployment ID, then: npx wrangler rollback [deployment-id] --env production
curl -X POST https://bot.613parts.ca/cron/run \
-H "authorization: Bearer $CRON_TRIGGER_TOKEN"
Used when AS400 missed the nightly run and you need today's routes processed manually.
cd worker npx wrangler deploy --env production --compatibility-date=$(date +%Y-%m-%d)
npx wrangler secret put SECRET_NAME --env production
# Overwrites whatever was there. No downtime.
worker/wrangler.toml and replace BOTH placeholder occurrences with the real ID from wrangler kv:namespace create. Redeploy.
npx wrangler r2 bucket list; if it doesn't appear, you might be on the wrong account — check wrangler whoami.
613parts.ca must be on Cloudflare DNS (active, not just added) for subdomain auto-provisioning. Wait for nameserver propagation; verify with dig 613parts.ca NS +short.
/login
The _redirects file didn't ship in dist/. Confirm: cat driver-app/dist/_redirects — should output /* /index.html 200. If missing, rebuild: cd driver-app && npm run build.
worker/src/lib/cors.ts. For now: hit drive.613parts.ca exactly (not www. or a different port). To add new origins, edit the ALLOWED_ORIGINS set + redeploy worker.
npx wrangler logout then npx wrangler login fresh.
| Phase | Trigger | Action |
|---|---|---|
| v1.0 lock | First IN3812D sample lands in R2 | Validate column names + payment enum against locked contract; tighten alias map; flip on prod cron at 04:00 EST. |
| v1.1 inline checkout | Stripe live keys verified | Build er-mint-stripe handler — replaces BUY_<sku> → human-handoff fallback with a live pay-link. |
| v1.2 VIN decode | NHTSA API verified | Build er-decode-vin — lets customers paste a VIN instead of using the year/make/model picker. |
| v1.3 returns pickup | Driver UX feedback | Emit returns to a separate pickups/{date}/{branch}.json route file. |