Skip to content

Deploy to Cloudflare

You need a Cloudflare account, a zone for your domain, and Wrangler logged in (npx wrangler login).

  1. Create the database and put its id into apps/web/wrangler.jsonc, and the bucket for photos of custom exercises:

    Terminal window
    npx wrangler d1 create gymgym
    npx wrangler r2 bucket create gymgym-media

    The bucket stays private: photos are served through the Worker, to their owner only. Without the MEDIA binding, photo uploads are simply turned off.

  2. Set your domain. Change the routes pattern, BETTER_AUTH_URL and PASSKEY_RP_ID in wrangler.jsonc.

  3. Add secrets.

    Terminal window
    cd apps/web
    npx wrangler secret put BETTER_AUTH_SECRET
    npx wrangler secret put GOOGLE_CLIENT_ID # and the other providers you want

    For Web Push reminders, generate VAPID keys with npx @pushforge/builder vapid and set VAPID_PUBLIC_KEY, VAPID_PRIVATE_JWK and VAPID_CONTACT.

  4. Deploy. This builds the site, applies D1 migrations and deploys the Worker:

    Terminal window
    corepack pnpm --filter @gymgym/web deploy
  5. Docs (optional). corepack pnpm --filter @gymgym/docs deploy publishes this site as static assets.

A staging environment is defined in wrangler.jsonc with its own database; deploy it with wrangler deploy --env staging.

People can add their own photo to an exercise they created. The browser shrinks it to 1024 px and re-encodes it, and the Worker re-parses the file and drops every EXIF, XMP and IPTC block before storing it in R2 under exercise/<id>, so no location or camera data is kept. Photos are deleted with the account, by “Reset everything” and when a backup is restored.

Exercise images and videos aren’t included because the usual sources aren’t freely licensed. If you have licensed media, host it (for example in a public R2 bucket) and set MEDIA_BASE_URL; the app shows media only when that variable is set.