Skip to main content

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.

systems.json is the single source of truth for every BCycle network that BCycle Map polls, stores, and displays. Every pipeline component — the poller Worker, the compaction script, the compute rollups, and the frontend’s NetworkPicker — reads the list through exactly one function, getSystems() in src/shared/systems.ts. Changing systems.json and redeploying the poller is all it takes to add or remove a network from the entire stack.

Schema

Each entry in systems.json maps to the following TypeScript type defined in src/shared/systems.ts:
export type SystemConfig = {
  system_id: string       // Unique slug — must match the GBFS URL path segment
  name: string            // Human-readable display name shown in the UI picker
  gbfs_url: string        // Full URL to the system's GBFS discovery JSON
  version: string         // GBFS spec version, e.g. "1.1"
  enabled?: boolean       // Omit or set true = active; false = paused (data preserved)
}
getSystems() returns only entries where enabled !== false, so the poller and all downstream compute scripts automatically skip disabled systems. getSystem(id) looks up any entry — including disabled ones — so historical data for a paused system remains resolvable.

Current systems.json

[
  {
    "system_id": "bcycle_santabarbara",
    "name": "Santa Barbara BCycle",
    "gbfs_url": "https://gbfs.bcycle.com/bcycle_santabarbara/gbfs.json",
    "version": "1.1"
  },
  {
    "system_id": "bcycle_cincyredbike",
    "name": "Red Bike - Cincinnati",
    "gbfs_url": "https://gbfs.bcycle.com/bcycle_cincyredbike/gbfs.json",
    "version": "1.1",
    "enabled": false
  }
]
Santa Barbara is the primary active system. Cincinnati is preserved but paused to stay under the Workers Free KV cap (see KV cap note below).

Adding a system

1
Append the entry to systems.json
2
Add a new object to the array. enabled is optional — omitting it (or setting true) makes the system active immediately on the next deploy.
3
{
  "system_id": "bcycle_madison",
  "name": "Madison BCycle",
  "gbfs_url": "https://gbfs.bcycle.com/bcycle_madison/gbfs.json",
  "version": "1.1"
}
4
system_id must match the slug in the GBFS URL exactly. See Finding system IDs below.
5
Redeploy the poller
6
The new entry is bundled into the Worker at deploy time. Until you redeploy, the running poller does not know about the new system.
7
gh workflow run deploy-workers.yml -f target=poller
8
Polling for the new system begins with the next cron tick (every 5 minutes).
9
Run corridors to update the NetworkPicker
10
The corridors workflow writes gbfs/systems-index.json — the file the read-API serves at /api/systems. The frontend uses it to populate the NetworkPicker dropdown.
11
gh workflow run corridors.yml
12
The NetworkPicker dropdown only renders when two or more systems are active. With a single active system the component hides itself automatically, so the picker appearing for the first time is a sign corridors ran successfully.
13
Wait for scheduled rollups
14
The other compute workflows — leaderboards, popularity, routes, travel-times, typicals — each read from getSystems() at runtime and pick up the new system automatically on their next scheduled execution. Trigger any of them manually from the Actions tab if you want data immediately rather than waiting for the schedule.

Enabling or disabling a system

Disabling a system stops the poller and all compute scripts from touching it, dropping its Cloudflare KV and R2 operations to zero. It does not delete any data. History frozen in R2 and the latest snapshot in KV are preserved intact; getSystem(id) still resolves the entry so historical API calls keep working. Re-enabling is fully lossless.

To disable

  1. Set "enabled": false on the entry in systems.json:
    {
      "system_id": "bcycle_cincyredbike",
      "name": "Red Bike - Cincinnati",
      "gbfs_url": "https://gbfs.bcycle.com/bcycle_cincyredbike/gbfs.json",
      "version": "1.1",
      "enabled": false
    }
    
  2. Redeploy the poller so it stops polling that system:
    gh workflow run deploy-workers.yml -f target=poller
    
  3. Run corridors to rewrite systems-index.json, which removes the system from the picker dropdown:
    gh workflow run corridors.yml
    

To re-enable

Remove "enabled": false (or set it to true), then repeat steps 2 and 3 above. The poller resumes on the next cron tick and historical data is immediately accessible again.

KV cap and the free tier

The Workers Free tier allows 1,000 KV puts per day. Each active system costs approximately 576 puts/day at the 5-minute polling interval (288 ticks/day × 2 mandatory puts per tick: one for the latest snapshot, one for the intra-hour buffer). Two active systems together require ~1,152 puts/day, which exceeds the free cap.If you are staying on the free tier, keep only one system enabled at a time. Disable the second with "enabled": false as shown above — its historical data is preserved and you can re-enable it anytime without data loss.

Finding system IDs

Browse the full BCycle GBFS index at https://gbfs.bcycle.com/. Each entry’s URL contains the system slug:
https://gbfs.bcycle.com/<system_id>/gbfs.json
                         ^^^^^^^^^^^
                         This is the system_id value
The system_id field in systems.json must match this slug exactly, including capitalisation (all lowercase for BCycle systems). A mismatch causes the poller to fetch the correct URL but store data under the wrong key, breaking the read API’s lookups.
You can validate that a GBFS URL is live before adding it to systems.json by curling it directly:
curl -s https://gbfs.bcycle.com/bcycle_madison/gbfs.json | jq .
A valid response includes a data object with language keys and feed URLs. A 404 means the system slug is wrong or the system has been retired.

Build docs developers (and LLMs) love