app · ios · running · submitted
bpm — Beats per Mile
v1.0.0 build 13 submitted to App Store review on 2026-05-17. Status: Waiting for Review. Apple SLA up to 48h. Match your music's BPM to your running cadence. RN + Expo, ships through prototype/. App Store bundle com.LinoLabs.BPM, team P692X2XP7N.
Workflow guard: bpm has its own PRD-driven workflow. PRD.md §13 is the live execution checklist — this umbrella does not write to it. The "What's left to do" below is a read-only mirror.
Where bpm stands — submitted, waiting
synced from ~/dev/bpm/PRD.md §13 as of 2026-05-17 · M1–M4 closed, M6.1 done
Done · in Apple's hands
- M1 — Spotify + Apple Music playback verified across TestFlight builds 9–13
- M2 — Run loop end-to-end, mood removed in favor of cadence-first, klips feature live, auto-advance + edge cases all handled
- M3 — Paywall + RevenueCat: entitlement pro, 3 IAPs (monthly/annual/lifetime), restore + manage subscription rows, sandbox-tested
- M4 — App icon, screenshots, store copy, privacy nutrition, age rating, support + privacy URLs (M4.3 preview video cut for v1)
- M6.1 — Build 13 submitted to App Store review on 2026-05-17
Waiting on Apple · up to 48h
- M6.2 Pass review (budget: 1 rejection cycle). Apple SLA up to 48h.
v1.1 followups — before review approves OR right after
- Sentry DSN — paste real DSN into app.json:extra.sentryDsn so day-1 crash data isn't blind. eas update can push without a rebuild.
- PostHog key — paste real key into app.json:extra.posthogApiKey so the install funnel is captured from day one.
- Support mailbox — support@beatspermile.app bounces. Set up Cloudflare Email Routing → forward to Gmail.
- GetSongBPM Worker proxy — key still ships in client bundle. Move calls behind the Cloudflare Worker (BPM_WORKER_URL) so the API key never leaves the server.
-
SecureStore migration — Spotify access + refresh tokens currently in AsyncStorage. Move to expo-secure-store (Keychain,
WHEN_UNLOCKED_THIS_DEVICE_ONLY). - RC server-truth gate — paywall currently trusts AsyncStorage. At run start, prefer live Purchases.getCustomerInfo() over cached entitlement.
M7 / M8 — Revenue gates
- M7.1 RevenueCat shows $100 gross cumulative
- M7.2 Identify the channel driving installs at $100
- M8.1 Month 1 ≥ $300 net
- M8.2 Month 2 ≥ $300 net
- M8.3 Month 3 ≥ $300 net — PRD complete
Android (cut from v1)
- M2.12a–f Android pipeline: EAS build, App Remote driver, sensor parity, background-audio service, source-picker hide, on-device verify. Reactivate post-iOS launch.
Where it lives
v1 in review| Repo | open ↗~/dev/bpm |
| Prototype | open ↗bpm/prototype/ |
| Marketing site | open ↗bpm/web/ |
| PRD (read-only here) | open ↗bpm/PRD.md |
| Ship status | open ↗bpm/SHIP-STATUS.html |
| Pitch | open ↗bpm/pitch.html |
klip feed
How bpm pipes signal back to klip:
- Replace like/save on run summary with a single klip button
- Klipped runs auto-create a klip profile post
- Music tracks the runner klipped become a klip-feed signal
Umbrella-level integration goals — implementation lives in the bpm + klip repos.
Landmines
- bpm/prototype/ — active Expo build dir; do not move.
- Bundle id com.LinoLabs.BPM is registered in App Store Connect. Don't rename.
- PRD.md edits must follow bpm/CLAUDE.md rules — surgical only. Umbrella never writes to PRD.md.
Lino Labs · bpm · status