Minimal iOS gym rest timer. Tap a preset, hear a buzzer, lift again.
Expo SDK 54, React Native, TypeScript. iOS-only v1. No backend, no analytics, no auth.
npm install
npx expo start
Then press i to open the iOS simulator, or scan the QR with Expo Go on a device.
npm install -g eas-clieas logineas build:configureeas build -p ios --profile productioneas submit -p ios --latestApp.tsx — entry; renders TimerScreen.screens/TimerScreen.tsx — the only screen.hooks/ — useTimer, usePresets, useNotifications.components/ — PresetButton, CountdownDisplay, CircularProgress, AddPresetModal, RunningControls.constants/ — colors, presets.utils/time.ts — MM:SS formatting.assets/ — icon, splash, adaptive icon, favicon. Regenerate via node scripts/generate-assets.mjs.Data Not Collected. No analytics, no crash reporting, no remote calls. AsyncStorage is the only persistence; it stays on the device.
App Privacy questionnaire answers (App Store Connect): Data Not Collected.
Required-reason APIs (PrivacyInfo.xcprivacy, auto-generated by Expo):
CA92.1 — UserDefaults, because AsyncStorage uses it on iOS.No additional entries needed. Verify the generated manifest in the .ipa via unzip -p Pauzer.ipa Payload/Pauzer.app/PrivacyInfo.xcprivacy.
Things the developer must still do manually:
com.tomasmach.pauzer in App Store Connect.eas login with Apple Developer credentials.eas build -p ios --profile production to produce an IPA.If tempted to add a feature, don’t. This app is intentionally boring. Widgets, Live Activities, Watch companion are explicitly v2.
One-time setup (developer machine):
curl -fsSL "https://get.maestro.mobile.dev" | bashnpm run ios:dev (runs npx expo run:ios). This compiles a .app with bundle id com.tomasmach.pauzer and installs it in the simulator.Run tests (after the app is installed in the booted simulator):
npm run test:e2e
Flows live under .maestro/:
start-and-cancel.yaml — tap 60s preset, verify countdown shows, cancel.add-custom-preset.yaml — add a 2:30 preset via the modal, verify tile appears.delete-custom-preset.yaml — add then long-press-delete a custom preset.Known caveats:
clearState to start from a clean AsyncStorage each run.