Skip to content

zachmja/strabang

Repository files navigation

strabang

Auto-renames your Strava activities with freshly generated Drake-style bars — the same idea as Bandók, but the titles are original lines in a Drake vibe instead of film quotes.

Connect your Strava account once. Every time you finish a run or ride, strabang catches the webhook event and renames the activity (e.g. "Turned all that doubt into distance — no days off").

Just want to use it? A hosted instance runs at https://strabang.backroomslabs.com — click Connect with Strava and you're done. Everything below is for people who want to run or modify their own copy.

How it works

Strava  --(activity created)-->  POST /webhook  -->  generate a line
   ^                                                       |
   |                                                       v
   +----------------  PUT /activities/{id} (name)  --------+
  1. OAuth/connect sends you to Strava; the callback stores your access + refresh tokens (activity:read_all,activity:write).
  2. Webhook — Strava POSTs a { aspect_type: "create" } event to /webhook. We ack immediately, then look up the activity, and rename it.
  3. Generatorsrc/lyrics/generator.ts composes an original line from themed phrase banks (the come-up, loyalty, the 6, the flex) with a seeded RNG.

The generated lines are original writing in a Drake-inspired style, not verbatim song lyrics, so there's nothing copyrighted bundled in the repo.

By default only Strava's auto-titles (Morning Run, Lunch Ride, …) are overwritten, so your own custom titles are left alone. Set RENAME_ALL=true to rename everything.

Setup

1. Create a Strava API application

At https://www.strava.com/settings/api create an app. Note the Client ID and Client Secret. Set the "Authorization Callback Domain" to the host of your BASE_URL (e.g. localhost for dev, or your deploy domain).

2. Configure environment

cp .env.example .env
# fill in STRAVA_CLIENT_ID and STRAVA_CLIENT_SECRET

3. Install and run

npm install
npm run dev          # tsx watch, http://localhost:3000
# or
npm run build && npm start

4. Expose a public HTTPS URL for the webhook

Strava must be able to reach /webhook. In dev, tunnel it:

ngrok http 3000
# set BASE_URL=https://<your-ngrok-subdomain>.ngrok.app in .env, then restart

5. Subscribe to webhook events

npm run webhook -- create   # Strava verifies via GET /webhook, then sends events
npm run webhook -- view     # inspect the current subscription
npm run webhook -- delete   # remove it

There can be only one push subscription per Strava application.

6. Connect your account

Open BASE_URL/connect, authorize, then log an activity. It gets renamed within a few seconds.

Configuration

Variable Default Purpose
STRAVA_CLIENT_ID Strava app client id (required)
STRAVA_CLIENT_SECRET Strava app client secret (required)
BASE_URL http://localhost:3000 Public URL Strava reaches
PORT 3000 Listen port
STRAVA_SCOPE activity:read_all,activity:write OAuth scopes
STRAVA_WEBHOOK_VERIFY_TOKEN strabang Echoed in the handshake
TOKEN_STORE_PATH data/tokens.json Where tokens are persisted
STATS_PATH data/stats.json Aggregate counters (total renames/connects — anonymous integers)
RENAME_ALL false Rename every activity vs. only default titles
LYRICS_EXPLICIT false Allow the profanity-included line banks (default is fully SFW; slurs are never generated in any mode)

Scripts

Command Description
npm run dev Run with hot reload
npm run build / npm start Compile to dist/ and run
npm test Run the vitest suite
npm run typecheck Type-check without emitting
npm run webhook -- <create|view|delete> Manage the push subscription

Project layout

src/
  config.ts             env loading + validation
  app.ts                express app factory (routes)
  index.ts              server bootstrap
  strava/
    client.ts           typed Strava v3 wrapper (oauth, get/update activity)
    types.ts            API + webhook payload types
  store/
    tokenStore.ts       TokenStore interface + file/memory implementations
  services/
    renamer.ts          token refresh + rename decision + action
  lyrics/
    generator.ts        original Drake-style line generator (seeded)
  scripts/
    manage-webhook.ts   subscription CLI
test/                   vitest unit tests

Notes

  • The JSON token store is fine for a single instance. For multi-instance deployments swap FileTokenStore for a database-backed TokenStore.
  • The webhook handler responds 200 before doing work, to stay within Strava's ~2s ack window.

Deploying to Railway

The repo ships a Dockerfile that any container host can run; the reference deployment is Railway: one always-on service plus a small persistent volume for the JSON token store. Webhooks need an always-reachable endpoint, so avoid hosts that sleep between requests.

1. Install the CLI and sign in

npm i -g @railway/cli   # or: brew install railway
railway login

2. Create the project, service, and volume

railway init --name strabang
railway add --service strabang
railway link --project strabang --service strabang
railway volume add --mount-path /data

The volume holds tokens.json; without it, every redeploy disconnects every athlete.

3. Set the variables

railway variables \
  --set "STRAVA_CLIENT_ID=..." \
  --set "STRAVA_CLIENT_SECRET=..." \
  --set "STRAVA_WEBHOOK_VERIFY_TOKEN=$(openssl rand -hex 16)" \
  --set "WEBHOOK_PATH_SECRET=$(openssl rand -hex 16)" \
  --set "TOKEN_STORE_PATH=/data/tokens.json" \
  --set "BASE_URL=https://<your-domain>"

(Railway injects PORT at runtime; the server reads it. For <your-domain>, either attach a custom domain with railway domain <your-domain> or run bare railway domain to generate a *.up.railway.app URL.)

4. Deploy

railway up --detach

After deploy, hit https://<your-domain>/healthz — should return {"ok": true}.

5. Update Strava and subscribe to webhooks

In https://www.strava.com/settings/api, set Authorization Callback Domain to your host (host only — no https://).

Then create the push subscription. The manage-webhook script runs from your local machine and just needs the same env vars in your local .env:

# in your local .env
STRAVA_CLIENT_ID=...
STRAVA_CLIENT_SECRET=...
STRAVA_WEBHOOK_VERIFY_TOKEN=<same as the Railway variable>
WEBHOOK_PATH_SECRET=<same as the Railway variable>
BASE_URL=https://<your-domain>

npm run webhook -- create

Strava will hit https://<your-domain>/webhook/<secret> to validate the callback. If you see { "id": <n> } in the script's output, you're live.

6. Connect your Strava account

Open https://<your-domain>/connect, authorize, then log an activity. It should be renamed within seconds.

Logs and ops

railway logs           # tail logs
railway status         # deployment state
railway ssh            # shell into the running container

Strava API Agreement compliance

If you're going to invite anyone other than yourself to use a strabang instance, you're operating under the Strava API Agreement. The clauses most relevant to strabang and how this repo handles them:

Clause How strabang handles it
No AI/ML training on Strava data The generator is templated/RNG, no external model calls.
7-day cache limit on Strava Data We don't cache — fetch the activity, decide, rename, discard.
Delete data on deauthorization The webhook handler drops tokens on the authorized=false event.
HTTPS for Strava data in transit All API calls hit https://www.strava.com; you must serve /webhook over HTTPS too.
Display only the requesting user's own data The post-connect page shows only the connected athlete's first name.
Brand Guidelines We use the official "Connect with Strava" button and "Powered by Strava" attribution.
Privacy policy required See PRIVACY.md. Set a contact address before inviting users.
Trademark restrictions The app name "Strabang" arguably echoes the Strava mark; if Strava ever objects, rename it.
Token storage security Default JSON store relies on filesystem perms; swap for an encrypted DB for multi-user deployments.

License

MIT.

About

Auto-renames your Strava activities with freshly generated Drake-style bars

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors