Session count alone says nothing about consistency, which is what makes pelvic floor training work. Record every completion timestamp and derive streaks from local calendar days: current streak (survives until a full day is missed), best streak, and a 14-day dot strip on the home screen. The done screen now shows the streak so finishing is rewarded. - src/lib/streak.ts: pure day-key / streak logic, covered by node --test - store: new `sessions` array, defaulted for pre-existing installs - home: StreakCard, screen now scrolls for smaller phones - tsconfig: TS 6 no longer auto-includes @types, so declare node types Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1.7 KiB
Kegel
Pelvic floor trainer for sexual performance — a free, local-only take on what Stamina was before it went paid. Expo / React Native, Android + iOS.
How it works
A session is four guided blocks driven by a step timer with haptic cues:
- Holds — 8 × squeeze-and-hold. This is the progressive-overload driver: holds start at 5s and grow +1s every 3 completed sessions (capped at 30s). Manual ±1s adjustment in Settings.
- Pushes — 5 × reverse kegel (gently bear down). Scales at half the rate of holds, capped at 12s.
- Quick squeezes — 10 × 1s burst contractions with 1s release.
- Quick pushes — 10 × 1s burst pushes with 1s release.
Progress (session count, difficulty adjustment, completion history) lives in AsyncStorage — no server, no account. The home screen shows your day streak (alive until a full day is missed), best streak, and a two-week activity strip.
Layout
src/app/— expo-router screens:index(home),session(timer),settingssrc/lib/workout.ts— pure session-plan + progression logicsrc/lib/streak.ts— pure streak / calendar-day logic (tested)src/lib/store.ts— tiny local store persisted to AsyncStorageandroid/— committed prebuild output; CI builds it directly
Development
npm install
npm start # Expo dev server
npm run typecheck
npm test # node --test over src/lib/*.test.ts
Release
Push to main → Gitea Actions on the desktop runner (runs-on: desktop,
never the VPS) builds a signed APK and publishes a Gitea release — install via
Obtainium. Keystore: ~/.android-keys/kegel-release.jks (repo secrets
KEYSTORE_B64, KEYSTORE_PASSWORD; alias kegel). iOS runs via
npx expo run:ios from a Mac.