$npx -y skills add rshankras/claude-code-apple-skills --skill announcement-bannerGenerates an in-app announcement banner system with remote configuration, scheduling, deep link actions, and dismiss tracking. Use when user wants in-app banners, promotional notices, maintenance alerts, or contextual announcements.
| 1 | # Announcement Banner Generator |
| 2 | |
| 3 | Generate a configurable in-app announcement/banner system that displays contextual messages (maintenance alerts, new feature highlights, promotions) from remote config or local definitions. Supports dismissal, deep link actions, and scheduling. |
| 4 | |
| 5 | ## When This Skill Activates |
| 6 | |
| 7 | Use this skill when the user: |
| 8 | - Asks to "add announcement banner" or "in-app banner" |
| 9 | - Wants "app announcement" or "notification banner" |
| 10 | - Mentions "promotional banner" or "promo banner" |
| 11 | - Asks about "maintenance notice" or "maintenance alert" |
| 12 | - Wants "in-app messaging" or "contextual banners" |
| 13 | - Asks to "show announcements" or "display alerts to users" |
| 14 | - Mentions "feature highlight banner" or "what's new banner" |
| 15 | |
| 16 | ## Pre-Generation Checks |
| 17 | |
| 18 | ### 1. Project Context Detection |
| 19 | - [ ] Check Swift version (requires Swift 5.9+) |
| 20 | - [ ] Check deployment target (iOS 16+ / macOS 13+) |
| 21 | - [ ] Check for @Observable support (iOS 17+ / macOS 14+) |
| 22 | - [ ] Identify source file locations |
| 23 | |
| 24 | ### 2. Conflict Detection |
| 25 | Search for existing banner/toast code: |
| 26 | ``` |
| 27 | Glob: **/*Banner*.swift, **/*Announcement*.swift, **/*Toast*.swift, **/*InAppMessage*.swift |
| 28 | Grep: "AnnouncementBanner" or "InAppBanner" or "ToastView" or "BannerView" |
| 29 | ``` |
| 30 | |
| 31 | If third-party library found (Firebase In-App Messaging, Braze, Intercom): |
| 32 | - Ask if user wants to replace or keep it |
| 33 | - If keeping, don't generate — advise on integration patterns instead |
| 34 | |
| 35 | ### 3. Deep Linking Detection |
| 36 | Check for existing deep linking setup: |
| 37 | ``` |
| 38 | Grep: "deepLink" or "DeepLink" or "universalLink" or "openURL" or "onOpenURL" |
| 39 | ``` |
| 40 | |
| 41 | If deep linking exists, integrate with it. If not, generate standalone action handling. |
| 42 | |
| 43 | ## Configuration Questions |
| 44 | |
| 45 | Ask user via AskUserQuestion: |
| 46 | |
| 47 | 1. **Banner position?** |
| 48 | - Top (slides in from top) — recommended for alerts |
| 49 | - Bottom (slides in from bottom) |
| 50 | - Floating (centered overlay with dimmed background) |
| 51 | |
| 52 | 2. **Content source?** |
| 53 | - Local only (hardcoded announcements in code) |
| 54 | - Remote JSON (fetch from server endpoint) |
| 55 | - Both (remote with local fallbacks) — recommended |
| 56 | |
| 57 | 3. **Action type?** |
| 58 | - Deep link (navigate to in-app screen) |
| 59 | - URL (open in Safari/SFSafariViewController) |
| 60 | - Dismiss only (informational, no action button) |
| 61 | - All of the above — recommended |
| 62 | |
| 63 | 4. **Include scheduling (start/end dates)?** |
| 64 | - Yes (time-limited announcements with date ranges) — recommended |
| 65 | - No (always-active until dismissed) |
| 66 | |
| 67 | ## Generation Process |
| 68 | |
| 69 | ### Step 1: Read Templates |
| 70 | Read `templates.md` for production Swift code. |
| 71 | |
| 72 | ### Step 2: Create Core Files |
| 73 | Generate these files: |
| 74 | 1. `Announcement.swift` — Model with style, action, priority, scheduling |
| 75 | 2. `AnnouncementManager.swift` — @Observable manager: loads, filters, tracks dismissals |
| 76 | 3. `AnnouncementProvider.swift` — Protocol + local/remote implementations with caching |
| 77 | |
| 78 | ### Step 3: Create UI Files |
| 79 | 4. `AnnouncementBannerView.swift` — SwiftUI banner with style-aware colors and animations |
| 80 | 5. `AnnouncementBannerModifier.swift` — ViewModifier for overlay placement and action routing |
| 81 | |
| 82 | ### Step 4: Create Optional Files |
| 83 | Based on configuration: |
| 84 | - `AnnouncementScheduler.swift` — If scheduling selected (date range filtering, timezone handling) |
| 85 | |
| 86 | ### Step 5: Determine File Location |
| 87 | Check project structure: |
| 88 | - If `Sources/` exists -> `Sources/AnnouncementBanner/` |
| 89 | - If `App/` exists -> `App/AnnouncementBanner/` |
| 90 | - Otherwise -> `AnnouncementBanner/` |
| 91 | |
| 92 | ## Output Format |
| 93 | |
| 94 | After generation, provide: |
| 95 | |
| 96 | ### Files Created |
| 97 | ``` |
| 98 | AnnouncementBanner/ |
| 99 | ├── Announcement.swift # Model with style, action, priority |
| 100 | ├── AnnouncementManager.swift # Observable manager with dismiss tracking |
| 101 | ├── AnnouncementProvider.swift # Protocol + local/remote providers |
| 102 | ├── AnnouncementBannerView.swift # SwiftUI banner view |
| 103 | ├── AnnouncementBannerModifier.swift# ViewModifier for overlay + actions |
| 104 | └── AnnouncementScheduler.swift # Date range filtering (optional) |
| 105 | ``` |
| 106 | |
| 107 | ### Integration Steps |
| 108 | |
| 109 | **Add banner overlay to root view:** |
| 110 | ```swift |
| 111 | // In your root ContentView or NavigationStack |
| 112 | ContentView() |
| 113 | .announcementBanner() |
| 114 | ``` |
| 115 | |
| 116 | **With custom position:** |
| 117 | ```swift |
| 118 | ContentView() |
| 119 | .announcementBanner(position: .bottom) |
| 120 | ``` |
| 121 | |
| 122 | **With deep link action handler:** |
| 123 | ```swift |
| 124 | ContentView() |
| 125 | .announcementBanner { action in |
| 126 | switch action { |
| 127 | case .deepLink(let destination): |
| 128 | router.navigate(to: destination) |
| 129 | case .url(let url): |
| 130 | openURL(url) |
| 131 | case .dismiss: |
| 132 | break |
| 133 | } |
| 134 | } |
| 135 | ``` |
| 136 | |
| 137 | **Define local announcements:** |
| 138 | ```swift |
| 139 | let provider = LocalAnnouncementProvider(annou |