$npx -y skills add rshankras/claude-code-apple-skills --skill lapsed-userGenerates lapsed user detection and re-engagement screens with personalized return experiences, win-back offers, and inactivity tracking. Use when user wants to re-engage inactive users, detect lapsed users, or build return flows.
| 1 | # Lapsed User Re-Engagement Generator |
| 2 | |
| 3 | Generate production infrastructure for detecting users who haven't opened the app in X days, showing personalized return screens that highlight what they missed, and optionally presenting win-back incentives to recover churned or lapsing users. |
| 4 | |
| 5 | ## When This Skill Activates |
| 6 | |
| 7 | Use this skill when the user: |
| 8 | - Asks about "lapsed user" detection or re-engagement |
| 9 | - Wants to handle "returning user" or "inactive user" scenarios |
| 10 | - Mentions "re-engagement" screens or flows |
| 11 | - Asks about "win-back" offers for churned users |
| 12 | - Wants to detect when a "user hasn't opened app" in a while |
| 13 | - Asks about "user retention" or "come back" experiences |
| 14 | |
| 15 | ## Pre-Generation Checks |
| 16 | |
| 17 | ### 1. Project Context Detection |
| 18 | - [ ] Check Swift version (requires Swift 5.9+) |
| 19 | - [ ] Check deployment target (iOS 17+ / macOS 14+ for @Observable) |
| 20 | - [ ] Identify source file locations and project structure |
| 21 | |
| 22 | ### 2. Existing Engagement Tracking |
| 23 | Search for existing engagement or analytics infrastructure: |
| 24 | ``` |
| 25 | Glob: **/*Analytics*.swift, **/*Engagement*.swift, **/*Tracker*.swift, **/*Activity*.swift |
| 26 | Grep: "lastActiveDate" or "UserDefaults" or "scenePhase" or "applicationDidBecomeActive" |
| 27 | ``` |
| 28 | |
| 29 | If existing tracking found: |
| 30 | - Ask if user wants to integrate with it or build standalone |
| 31 | - If integrating, adapt templates to use existing storage/events |
| 32 | |
| 33 | ### 3. Push Notification Setup |
| 34 | Search for existing push notification configuration: |
| 35 | ``` |
| 36 | Glob: **/*Notification*.swift, **/*Push*.swift |
| 37 | Grep: "UNUserNotificationCenter" or "UNNotification" or "registerForRemoteNotifications" |
| 38 | ``` |
| 39 | |
| 40 | If push notifications are configured, offer push-based re-engagement as an option. |
| 41 | |
| 42 | ### 4. Conflict Detection |
| 43 | Search for existing lapsed user handling: |
| 44 | ``` |
| 45 | Glob: **/*LapsedUser*.swift, **/*WinBack*.swift, **/*ReturnExperience*.swift, **/*Reengag*.swift |
| 46 | Grep: "lapsedUser" or "winBack" or "returnExperience" or "daysInactive" |
| 47 | ``` |
| 48 | |
| 49 | If existing implementation found: |
| 50 | - Ask if user wants to replace or extend it |
| 51 | - If extending, generate only the missing pieces |
| 52 | |
| 53 | ## Configuration Questions |
| 54 | |
| 55 | Ask user via AskUserQuestion: |
| 56 | |
| 57 | 1. **Inactivity threshold?** |
| 58 | - 7 days (light engagement apps — social, news) |
| 59 | - 14 days (moderate engagement — productivity, fitness) — recommended |
| 60 | - 30 days (low-frequency apps — finance, travel) |
| 61 | - Custom (user specifies days) |
| 62 | |
| 63 | 2. **Re-engagement strategy?** |
| 64 | - What-You-Missed (highlight new content, features, or activity since last visit) |
| 65 | - Special Offer (discount or extended trial for lapsed subscribers) |
| 66 | - Fresh Start (reset onboarding highlights, re-introduce key features) |
| 67 | - All of the above (tiered by lapse duration) |
| 68 | |
| 69 | 3. **Trigger mechanism?** |
| 70 | - Show on app return (present sheet when user opens app after inactivity) |
| 71 | - Via push notification (schedule local notification after X days inactive) |
| 72 | - Both — recommended |
| 73 | |
| 74 | 4. **Include analytics events?** |
| 75 | - Yes (track lapse detection, return screen shown, CTA tapped, offer redeemed) — recommended |
| 76 | - No (skip analytics, just UI) |
| 77 | |
| 78 | ## Generation Process |
| 79 | |
| 80 | ### Step 1: Read Templates |
| 81 | Read `templates.md` for production Swift code. |
| 82 | |
| 83 | ### Step 2: Create Core Files |
| 84 | Generate these files: |
| 85 | 1. `InactivityTracker.swift` — Tracks last active date, calculates days since last use |
| 86 | 2. `LapsedUserDetector.swift` — Evaluates inactivity against thresholds, returns lapse category |
| 87 | 3. `LapsedUserManager.swift` — Orchestrator combining detection + experience selection + analytics |
| 88 | |
| 89 | ### Step 3: Create UI Files |
| 90 | 4. `ReturnExperienceView.swift` — Personalized "Welcome back" screen with what-you-missed |
| 91 | 5. `WinBackOfferView.swift` — Special offer screen for lapsed subscribers |
| 92 | |
| 93 | ### Step 4: Create Integration File |
| 94 | 6. `LapsedUserModifier.swift` — SwiftUI ViewModifier for root view auto-detection and presentation |
| 95 | |
| 96 | ### Step 5: Determine File Location |
| 97 | Check project structure: |
| 98 | - If `Sources/` exists → `Sources/LapsedUser/` |
| 99 | - If `App/` exists → `App/LapsedUser/` |
| 100 | - Otherwise → `LapsedUser/` |
| 101 | |
| 102 | ## Output Format |
| 103 | |
| 104 | After generation, provide: |
| 105 | |
| 106 | ### Files Created |
| 107 | ``` |
| 108 | LapsedUser/ |
| 109 | ├── InactivityTracker.swift # Tracks last active date in UserDefaults |
| 110 | ├── LapsedUserDetector.swift # Evaluates inactivity thresholds |
| 111 | ├── LapsedUserManager.swift # Orchestrator for detection + experience |
| 112 | ├── ReturnExperienceView.swift # Welcome back screen with highlights |
| 113 | ├── WinBackOfferView.swift # Special offer for lapsed subscribers |
| 114 | └── LapsedUserModifier.swift # ViewModifier for auto-detection |
| 115 | ``` |
| 116 | |
| 117 | ### Integration at App Launch |
| 118 | |
| 119 | **Attach to root view:** |
| 120 | ```swift |
| 121 | @main |
| 122 | struct MyApp: App { |
| 123 | var body: so |