Bad shot? Blame everything but yourself.
A golf excuse generator built with React Native.
Tap or shake your phone to generate a random golf excuse. Copy it, share it, blame anything but your swing.
- 270+ excuses across 7 categories (Weather, Equipment, Course, Body, Mental, Blame, Luck)
- Shake to generate (just shake your phone for a new excuse)
- Copy and share with one tap
- Per-excuse voting (anonymous, deduplicated by random device UUID)
- Global counter shows total excuses generated across all users
- Haptic feedback on every action
- Weekly local notifications (opt-in): Thursday 18:00 and Sunday 10:00 with a random alibi
- In-app rating prompt after 5 generations (only asked once per install)
- In-app updates via Expo Updates
- Works offline for excuse generation; vote and counter sync when online
- Android tablets and foldables: adaptive layout, scrolls in landscape
| Layer | Technology |
|---|---|
| Framework | React Native + Expo SDK 54 (new architecture) |
| Language | JavaScript |
| Storage | AsyncStorage |
| Haptics | Expo Haptics |
| Sensors | Expo Sensors (shake detection) |
| Notifications | Expo Notifications (local only, weekly schedule) |
| Share card | react-native-view-shot (on-device 1080x1350 PNG capture) |
| Backend | Next.js API at excusecaddie.xyz (Supabase + Upstash KV under the hood) |
| Android target | API 36 (Android 16) via expo-build-properties |
No third-party analytics SDK. The only network calls go to our own backend.
git clone https://github.com/dotsystemsdevs/excuse-caddie.git
cd excuse-caddie/app
npm install
npx expo startnpx expo run:android # local Android build + install
npx expo run:ios # local iOS build + install
npx expo start --web # browser previewRequirements: Node.js 18+, Expo CLI. For Android target SDK 36 builds you need Android SDK 36 installed locally or use EAS Build.
App.js Main app component (single file)
src/
api.js Backend client (excusecaddie.xyz votes + counter)
constants.js Config, palette, spacing, fonts
excuses.js 270+ excuses with categories and tags
excuse-ids.js Stable hash IDs for vote deduplication
utils.js pickWeighted, helpers
sounds.js Mulligan tap sound playback
notifications.js Weekly local notification scheduling
prefs.js Local preference storage helpers
assets/ Icons, logo, splash, sound clips
screenshots/ App Store and Play Store screenshots
backend/ Backend schema and setup notes (lives on excusecaddie.xyz)
No accounts. No third-party tracking. No ads.
What the app sends to our backend:
- An anonymous random UUID (generated on first launch, stored locally) is sent with each vote so one device counts as one vote per excuse.
- An anonymous counter bump request (no device ID attached) every time you tap Mulligan, so the global "alibis on the card" counter stays accurate.
What stays on your device:
- The UUID, notification preference, generation count, and rating-prompt timestamp.
What we do not collect:
- Names, emails, accounts, location, ad IDs, contacts, or any cross-app identifiers.
Full details: Privacy Policy.
MIT






