Overview
SanMarcSoft uses Cloudflare Workers for edge computing. Workers are deployed via either wrangler deploy or the Cloudflare API directly. Key workers include the badges worker, URL shortener, and waitlist.
Prerequisites
- Cloudflare API token:
pass cloudflare/api-token - Cloudflare Account ID:
pass cloudflare/account-id - Wrangler CLI:
npm install -g wrangler or use project-local npx wrangler
Method 1: Wrangler Deploy (Preferred)
Standard Deploy
1
2
| cd /path/to/worker
npx wrangler deploy
|
Wrangler reads wrangler.toml for configuration including bindings, routes, and compatibility settings.
Deploy with Environment
1
2
| npx wrangler deploy --env production
npx wrangler deploy --env testing
|
Method 2: API Deploy (When Wrangler Fails)
Use the Cloudflare API directly when wrangler has issues with bindings or versioning. This is a multipart form upload.
Step 1: Prepare the Worker Script
Bundle the worker into a single file if needed:
1
| npx esbuild src/index.ts --bundle --outfile=dist/worker.js --format=esm --target=es2022
|
Create a metadata.json file with all bindings:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| {
"main_module": "worker.js",
"bindings": [
{
"type": "d1",
"name": "DB",
"id": "<d1-database-id>"
},
{
"type": "kv_namespace",
"name": "CACHE",
"id": "<kv-namespace-id>"
},
{
"type": "secret_text",
"name": "API_KEY",
"text": ""
}
],
"compatibility_date": "2024-01-01",
"compatibility_flags": []
}
|
Note: Secret bindings in metadata should have empty text values. Set actual secret values separately via the secrets API.
Step 3: Upload via API
1
2
3
4
5
6
7
8
9
| CF_TOKEN=$(pass cloudflare/api-token)
ACCOUNT_ID=$(pass cloudflare/account-id)
WORKER_NAME="verifieddit-badges"
curl -s -X PUT \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-F "worker.js=@dist/worker.js;type=application/javascript+module" \
-F "metadata=@metadata.json;type=application/json"
|
Setting Worker Secrets
Secrets are set independently of deployment. They persist across deploys.
1
2
3
4
5
6
7
8
9
10
| # Set a single secret
curl -s -X PUT \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}/secrets" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "SIGHTENGINE_API_USER",
"text": "'"$(pass sightengine/api-user)"'",
"type": "secret_text"
}'
|
Bulk Secret Setting
1
2
3
4
5
6
7
8
9
10
11
12
13
| # List of secrets to set from pass store
for SECRET_NAME in SIGHTENGINE_API_USER SIGHTENGINE_API_SECRET CLERK_SECRET_KEY STRIPE_SECRET_KEY; do
PASS_PATH="verifieddit/${SECRET_NAME,,}" # lowercase pass path
VALUE=$(pass "${PASS_PATH}")
curl -s -X PUT \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}/secrets" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"name\": \"${SECRET_NAME}\", \"text\": \"${VALUE}\", \"type\": \"secret_text\"}"
echo "Set ${SECRET_NAME}"
done
|
Version Management
Known Issue: Worker Versioning Conflicts
Cloudflare Workers have a versioning system that can cause deployment failures. When deploying via the API, you may encounter version conflicts if a previous deployment created versions.
Symptoms:
- Deploy succeeds but old code still runs
- API returns success but changes are not reflected
- Dashboard shows multiple versions with “gradual rollout” percentages
Resolution:
- Check current versions:
1
2
| curl -s "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}/versions" \
-H "Authorization: Bearer ${CF_TOKEN}" | jq '.result'
|
- If multiple versions exist with gradual rollout, set 100% traffic to the latest version:
1
2
3
4
5
6
| VERSION_ID="<latest-version-id>"
curl -s -X PATCH \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}/versions/${VERSION_ID}" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type: application/json" \
--data '{"percentage": 100}'
|
- Alternatively, delete and recreate the worker (last resort):
1
2
3
4
5
6
7
| # Delete
curl -s -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}" \
-H "Authorization: Bearer ${CF_TOKEN}"
# Re-deploy
npx wrangler deploy
|
Checking Deployed Version
Add a debug endpoint to your worker to verify the running version:
1
2
3
4
5
6
7
| // In your worker
if (url.pathname === '/__debug') {
return new Response(JSON.stringify({
version: '2026-03-21',
deployed: new Date().toISOString(),
}), { headers: { 'content-type': 'application/json' } });
}
|
1
| curl -s https://worker-route.example.com/__debug | jq .
|
Route Configuration
Adding Routes via API
1
2
3
4
5
6
7
8
| curl -s -X POST \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/workers/routes" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"pattern": "example.com/api/*",
"script": "worker-name"
}'
|
Listing Routes
1
2
| curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/workers/routes" \
-H "Authorization: Bearer ${CF_TOKEN}" | jq '.result[] | {pattern, script}'
|
Tail / Logging
1
2
3
4
5
6
| # Live tail worker logs
npx wrangler tail <worker-name>
# With filters
npx wrangler tail <worker-name> --status error
npx wrangler tail <worker-name> --search "sightengine"
|
Troubleshooting
- “Script not found” after deploy: Check that the worker name matches the route configuration. Worker names are case-sensitive.
- Bindings missing after API deploy: Bindings must be included in every API deploy. Unlike secrets, bindings are not persisted separately.
- D1 binding not working: Ensure the D1 database ID in metadata matches the actual database. Verify with
npx wrangler d1 list. - Secrets cleared after deploy: Secrets should persist across deploys, but if deploying via API with a new script, re-set all secrets after deployment.