BCycle Map runs entirely on Cloudflare’s free tier — three Workers, one KV namespace, and one R2 bucket. None of these resources exist in a fresh account until you provision them. This guide walks through every step exactly once, from authenticating Wrangler to verifying that the poller is writing live data. Each command must be run from the repository root unless stated otherwise.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/samgutentag/bcycle-map/llms.txt
Use this file to discover all available pages before exploring further.
Log in with your Cloudflare account via browser OAuth, then capture your Account ID — you will need it for the GitHub Actions secrets in a later step.
npx wrangler login # opens a browser window for OAuth
npx wrangler whoami # prints your email and Account ID
The KV namespace stores both the latest GBFS snapshot (hot path, served by the read API) and the intra-hour buffer keys (sealed into parquet by the compaction job). You need a production namespace and a preview namespace for local
wrangler dev runs.npx wrangler kv namespace create GBFS_KV # production
npx wrangler kv namespace create GBFS_KV --preview # preview (local dev)
Each command prints an
id. Open all three TOML files and replace every PLACEHOLDER_REPLACE_AT_DEPLOY with the appropriate value:# In wrangler.toml, wrangler.read-api.toml, and wrangler.smoke.toml
[[kv_namespaces]]
binding = "GBFS_KV"
id = "<production-id-from-first-command>"
preview_id = "<preview-id-from-second-command>"
Save the production
id — it becomes the CF_KV_NAMESPACE_ID GitHub secret used by the compaction workflow.The R2 bucket (
bcycle-map-archive) holds compacted parquet partitions written by the hourly GitHub Actions job. Create the bucket, then enable its public URL and add a CORS policy so the frontend can fetch parquet files directly from R2 in the browser.In the Cloudflare dashboard navigate to R2 → bcycle-map-archive → Settings → Public Development URL → Allow Access. Cloudflare assigns a
https://pub-<hash>.r2.dev URL — copy it. This becomes VITE_R2_PUBLIC_URL in .env.local.The wildcard
AllowedOrigins is appropriate here. GBFS station data is
publicly available information — BCycle publishes it openly — and R2 has no
egress fees, so there is no cost or security exposure from allowing any
origin to read the bucket. Tighten the policy to your production domain if
your use case ever changes.In the dashboard: R2 → Manage API Tokens → Create API Token. Choose Object Read & Write and scope it to the
bcycle-map-archive bucket. Save both the Access Key ID and the Secret Access Key — the secret is shown only once. These become the R2_ACCESS_KEY_ID and R2_SECRET_ACCESS_KEY GitHub secrets.With the KV namespace IDs in place, deploy all three Workers. Each prints its
*.workers.dev URL on success.# Poller: scheduled every 5 minutes, writes GBFS snapshots to KV
npx wrangler deploy
# Read API: HTTP Worker serving /api/systems/:id/current (and more)
npx wrangler deploy --config wrangler.read-api.toml
# Smoke: daily cron at 09:00 UTC, files a GitHub Issue on data errors
npx wrangler deploy --config wrangler.smoke.toml
Save the read-API URL printed by the second command — it looks like
https://bcycle-map-read-api.<your-account>.workers.dev. The frontend needs it in the next step.VITE_API_BASE=https://bcycle-map-read-api.<your-account>.workers.dev
VITE_R2_PUBLIC_URL=https://pub-<hash>.r2.dev
Replace both placeholders with the values captured in the previous steps. Now
npm run dev:web fetches live data from your deployed Worker without needing any local Workers running.Open GitHub → Settings → Secrets and variables → Actions and add the following repository secrets so the compaction and deployment workflows have the credentials they need:
CF_ACCOUNT_IDCLOUDFLARE_API_TOKENCF_KV_API_TOKENCF_KV_NAMESPACE_IDid from Step 2R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_BUCKETbcycle-map-archiveSee the Environment Variables reference for full details on creating each token with the correct permission template.
curl https://bcycle-map-read-api.<your-account>.workers.dev/api/systems/bcycle_santabarbara/current
A successful response is a JSON object containing station information with roughly 85 stations for Santa Barbara. If you receive a
not found error, the cron has not fired yet — wait one more polling interval and retry.You can also trigger the compaction workflow manually to verify the GitHub Actions secrets are all correct: