diff --git a/README.md b/README.md index d415c42..d7737f8 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ clix doctor ### `clix ios-setup` -Configure iOS capabilities required for the Clix SDK (Push Notifications and App Groups). +Configure iOS capabilities and Notification Service Extension (NSE) for the Clix SDK. ```bash clix ios-setup @@ -170,9 +170,14 @@ clix ios-setup **What it does:** 1. Analyzes your iOS project structure -2. Checks current capabilities status +2. Checks current capabilities status (Push Notifications, App Groups) 3. Creates/modifies entitlements files -4. Guides you through Xcode and Apple Developer Portal configuration +4. Guides NSE setup for rich push notifications: + - Creates `{AppName}NotificationServiceExtension` target + - Implements `NotificationService.swift` with `ClixNotificationServiceExtension` + - Configures CocoaPods/SPM dependencies for extension target + - Sets build settings (`ENABLE_USER_SCRIPT_SANDBOXING` for Xcode 15+) +5. Guides you through Xcode and Apple Developer Portal configuration **Note:** Some steps require manual action in Xcode and Apple Developer Portal. @@ -277,7 +282,7 @@ Use these commands within the interactive chat (`clix`): | `/install` | | Autonomous SDK installation | | `/doctor` | | Check SDK integration status | | `/debug` | | Interactive debugging assistant | -| `/ios-setup` | `/capabilities`, `/ios-capabilities` | Configure iOS capabilities | +| `/ios-setup` | `/capabilities`, `/ios-capabilities` | Configure iOS capabilities and NSE | ### Interactive Skills diff --git a/llms.txt b/llms.txt index 0bcc9d3..0516d81 100644 --- a/llms.txt +++ b/llms.txt @@ -241,7 +241,7 @@ These can be run from command-line (`clix `) or chat mode: - `/install` - Autonomous SDK installation with automatic file modifications - `/doctor` - Analyze SDK integration status (automatic scan, JSON output) - `/debug` - Interactive debugging assistant (asks for problem description) -- `/ios-setup` (aliases: `/capabilities`, `/ios-capabilities`) - Configure iOS capabilities for push notifications and app groups +- `/ios-setup` (aliases: `/capabilities`, `/ios-capabilities`) - Configure iOS capabilities and Notification Service Extension (NSE) #### Interactive Skills (5 commands) @@ -380,32 +380,44 @@ Describe the problem: Events not appearing in Clix dashboard [Provides fix with exact file location] ``` -#### `/ios-setup` - iOS Setup & Capabilities Configuration +#### `/ios-setup` - iOS Setup, Capabilities & NSE Configuration **Category:** Autonomous Command **Aliases:** `/capabilities`, `/ios-capabilities` -**What it does:** Configures iOS capabilities required for the Clix SDK, specifically Push Notifications and App Groups. +**What it does:** Configures iOS capabilities and Notification Service Extension (NSE) required for the Clix SDK. **Capabilities configured:** - **Push Notifications** - Enables APNs communication (entitlement: `aps-environment`) -- **App Groups** - Enables data sharing between app and Notification Service Extension (entitlement: `com.apple.security.application-groups`, format: `group.clix.{BUNDLE_ID}`) +- **App Groups** - Enables data sharing between app and NSE (entitlement: `com.apple.security.application-groups`, format: `group.clix.{BUNDLE_ID}`) + +**Notification Service Extension (NSE) setup:** +- **Target name:** `{AppName}NotificationServiceExtension` (consistent across all steps) +- **NotificationService.swift:** Uses `ClixNotificationServiceExtension` base class with `register(projectId:)` call +- **Dependency setup:** CocoaPods (`pod 'Clix'` in extension target) or SPM (add Clix package to extension) +- **Build settings:** `ENABLE_USER_SCRIPT_SANDBOXING = No` for Xcode 15+ +- **React Native + Firebase:** Move "Embed Foundation Extensions" above "[RNFB] Core Configuration" **Workflow:** 1. Analyzes iOS project structure (finds .xcodeproj/.xcworkspace) 2. Detects Bundle ID and checks current capabilities status 3. Creates/modifies entitlements files for main app and extension -4. Provides step-by-step instructions for Xcode configuration -5. Guides through Apple Developer Portal setup -6. Outputs verification report +4. Guides NSE target creation and NotificationService.swift implementation +5. Provides CocoaPods/SPM setup instructions for extension target +6. Provides step-by-step instructions for Xcode configuration +7. Guides through Apple Developer Portal setup +8. Outputs verification report **What can be automated:** - Creating/modifying entitlements files - Reading project configuration **What requires manual action:** +- Creating NSE target in Xcode (File > New > Target > Notification Service Extension) - Adding capabilities in Xcode UI (Signing & Capabilities) +- Adding Clix SDK to extension target (Podfile or SPM) +- Configuring build settings for Xcode 15+ - Enabling capabilities in Apple Developer Portal - Registering App Group IDs - Regenerating provisioning profiles @@ -420,12 +432,14 @@ App Groups: not configured Creating entitlements files... ✓ Created MyApp.entitlements -✓ Created NotificationServiceExtension.entitlements +✓ Created MyAppNotificationServiceExtension.entitlements -Manual steps required in Xcode: -1. Add Push Notifications capability to main target -2. Add App Groups capability with ID: group.clix.com.example.myapp -3. Add same App Group to extension target +Manual steps required: +1. Create NSE target: MyAppNotificationServiceExtension +2. Implement NotificationService.swift with ClixNotificationServiceExtension +3. Add Clix SDK to extension (Podfile or SPM) +4. Add Push Notifications and App Groups capabilities +5. Set ENABLE_USER_SCRIPT_SANDBOXING to No (Xcode 15+) {verification report JSON} ``` @@ -1254,7 +1268,7 @@ When helping users with Clix CLI, keep these points in mind: - "SDK integration" → Use `/install` for autonomous installation or `/integration` skill for guided steps - "iOS installation" → Detect: Package.swift (SPM, preferred), Podfile (CocoaPods), or suggest SPM for bare Xcode projects. SPM is the modern, recommended approach. - "SPM/Swift Package Manager" → Guide through Package.swift modification or Xcode UI (File > Add Package Dependencies) for adding packages -- "iOS capabilities" → Use `/ios-setup` to configure Push Notifications and App Groups +- "iOS capabilities" → Use `/ios-setup` to configure Push Notifications, App Groups, and Notification Service Extension (NSE) - "Event tracking" → Use `/event-tracking` skill (interactive, creates event plans) - "User management" → Use `/user-management` skill (setUserId, properties, logout handling) - "Personalization" → Use `/personalization` skill (Liquid templates for messages) diff --git a/src/lib/embedded-skills.ts b/src/lib/embedded-skills.ts index c76dbd3..4aa57c5 100644 --- a/src/lib/embedded-skills.ts +++ b/src/lib/embedded-skills.ts @@ -1246,6 +1246,32 @@ Only these require user action: For these, provide brief instructions but don't wait for confirmation. +### iOS Notification Service Extension (Recommended) + +For rich push notifications (images, buttons), create a Notification Service Extension: + +1. In Xcode: File > New > Target > Notification Service Extension +2. Add Clix SDK to the extension target: + - **CocoaPods**: Add \`target 'YourExtension' do pod 'Clix' end\` to Podfile, then \`pod install\` + - **SPM**: Add Clix package to extension target in Xcode (General > Frameworks) +3. Implement NotificationService.swift: + \`\`\`swift + import UserNotifications + import Clix + + class NotificationService: ClixNotificationServiceExtension { + override func didReceive(_ request: UNNotificationRequest, + withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + register(projectId: "YOUR_PROJECT_ID") + super.didReceive(request, withContentHandler: contentHandler) + } + } + \`\`\` +4. Add App Groups capability to both main app and extension (same group ID: \`group.clix.{BUNDLE_ID}\`) +5. For Xcode 15+: Set \`ENABLE_USER_SCRIPT_SANDBOXING\` to "No" in extension's Build Settings + +For detailed setup, run \`clix ios-setup\` or \`/ios-setup\` in interactive mode. + ## Output Format After completion, report: @@ -1486,6 +1512,61 @@ Create or modify entitlements files. Use Write/Edit tools for these operations. **Note:** Replace \`{BUNDLE_ID}\` with the actual bundle identifier (e.g., \`com.example.myapp\`). +### Phase 3.5: Notification Service Extension Setup + +Create a Notification Service Extension for rich push notifications (images, buttons, etc.). + +**Create Extension Target in Xcode:** +\`\`\`text +1. File > New > Target +2. Select "Notification Service Extension" +3. Name it "{AppName}NotificationServiceExtension" (e.g., "MyAppNotificationServiceExtension") +4. Click "Finish" (Cancel the "Activate scheme" dialog) +5. Note: Use this exact name consistently in Podfile, entitlements path, and SPM setup +\`\`\` + +**Implement NotificationService.swift:** + +\`\`\`swift +import UserNotifications +import Clix + +class NotificationService: ClixNotificationServiceExtension { + override func didReceive( + _ request: UNNotificationRequest, + withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void + ) { + register(projectId: "YOUR_PROJECT_ID") + super.didReceive(request, withContentHandler: contentHandler) + } +} +\`\`\` + +**Note:** Replace \`YOUR_PROJECT_ID\` with your actual Clix project ID from + +**Add Clix SDK to Extension Target:** + +For CocoaPods projects, add to Podfile: +\`\`\`ruby +target '{AppName}NotificationServiceExtension' do + pod 'Clix' +end +\`\`\` +Then run: \`cd ios && pod install\` + +For SPM projects in Xcode: +1. Select the extension target +2. Go to General > Frameworks, Libraries, and Embedded Content +3. Click + and add the Clix package + +**Configure Build Settings (Xcode 15+):** + +For the extension target: +- Set \`ENABLE_USER_SCRIPT_SANDBOXING\` to "No" in Build Settings + +For React Native projects with Firebase: +- In Build Phases, move "Embed Foundation Extensions" above "[RNFB] Core Configuration" + ### Phase 4: Apple Developer Portal Configuration Guide user through manual portal configuration. These steps CANNOT be automated. diff --git a/src/lib/ios/agent-prompt-generator.ts b/src/lib/ios/agent-prompt-generator.ts index 198c6a5..32f2f16 100644 --- a/src/lib/ios/agent-prompt-generator.ts +++ b/src/lib/ios/agent-prompt-generator.ts @@ -43,8 +43,8 @@ Modify the Xcode project file (.pbxproj) to link the entitlements file: #### 2. Create Notification Service Extension [Required] Create a new Notification Service Extension target for rich push notifications: -- Target name: \`${context.appName}NotificationServiceExtension\` or \`NotificationServiceExtension\` -- Bundle ID: \`${context.bundleId}.NotificationServiceExtension\` +- Target name: \`${context.appName}NotificationServiceExtension\` +- Bundle ID: \`${context.bundleId}.${context.appName}NotificationServiceExtension\` - Deployment target: Same as main app or iOS 14.0+ - Create necessary files in the extension directory @@ -53,41 +53,40 @@ Create the NotificationService.swift file with Clix SDK integration: \`\`\`swift import UserNotifications -import ClixSDK - -class NotificationService: UNNotificationServiceExtension { - var contentHandler: ((UNNotificationContent) -> Void)? - var bestAttemptContent: UNMutableNotificationContent? +import Clix +class NotificationService: ClixNotificationServiceExtension { override func didReceive( _ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void ) { - self.contentHandler = contentHandler - bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) - - if let bestAttemptContent = bestAttemptContent { - // Let Clix SDK handle the notification - Clix.shared.handleNotificationServiceExtension( - request: request, - content: bestAttemptContent - ) { processedContent in - contentHandler(processedContent) - } - } - } - - override func serviceExtensionTimeWillExpire() { - if let contentHandler = contentHandler, - let bestAttemptContent = bestAttemptContent { - contentHandler(bestAttemptContent) - } + register(projectId: "YOUR_PROJECT_ID") + super.didReceive(request, withContentHandler: contentHandler) } } \`\`\` -#### 4. Create Extension Entitlements [Required] -Create entitlements file for the extension at \`${context.iosDir}/NotificationServiceExtension/NotificationServiceExtension.entitlements\`: +**Note:** Replace \`YOUR_PROJECT_ID\` with your actual Clix project ID from https://console.clix.so/ + +#### 4. Add Clix SDK to Extension Target [Required] + +**For CocoaPods projects:** +Add to your Podfile: +\`\`\`ruby +target '${context.appName}NotificationServiceExtension' do + pod 'Clix' +end +\`\`\` +Then run: \`cd ios && pod install\` + +**For SPM projects:** +In Xcode: +1. Select the extension target +2. Go to General > Frameworks, Libraries, and Embedded Content +3. Click + and add the Clix package + +#### 5. Create Extension Entitlements [Required] +Create entitlements file for the extension at \`${context.iosDir}/${context.appName}NotificationServiceExtension/${context.appName}NotificationServiceExtension.entitlements\`: \`\`\`xml @@ -102,7 +101,7 @@ Create entitlements file for the extension at \`${context.iosDir}/NotificationSe \`\`\` -#### 5. Update Extension Info.plist [Required] +#### 6. Update Extension Info.plist [Required] Ensure the extension's Info.plist has the correct NSExtension configuration: \`\`\`xml @@ -115,11 +114,19 @@ Ensure the extension's Info.plist has the correct NSExtension configuration: \`\`\` +#### 7. Configure Build Settings [Required - Xcode 15+] + +For the extension target in Xcode: +- Set \`ENABLE_USER_SCRIPT_SANDBOXING\` to "No" in Build Settings + +For React Native projects with Firebase: +- In Build Phases, move "Embed Foundation Extensions" above "[RNFB] Core Configuration" + ### Important Notes - The extension must share the same App Group as the main app - The extension's bundle ID must be a child of the main app's bundle ID -- Add the ClixSDK to the extension target's frameworks - Ensure the extension is added to the app's "Embed App Extensions" build phase +- Replace \`YOUR_PROJECT_ID\` with your actual Clix project ID Please complete these tasks by modifying the Xcode project files directly.`; } diff --git a/src/lib/skills/install/SKILL.md b/src/lib/skills/install/SKILL.md index 854c490..810806a 100644 --- a/src/lib/skills/install/SKILL.md +++ b/src/lib/skills/install/SKILL.md @@ -163,6 +163,32 @@ Only these require user action: For these, provide brief instructions but don't wait for confirmation. +### iOS Notification Service Extension (Recommended) + +For rich push notifications (images, buttons), create a Notification Service Extension: + +1. In Xcode: File > New > Target > Notification Service Extension +2. Add Clix SDK to the extension target: + - **CocoaPods**: Add `target 'YourExtension' do pod 'Clix' end` to Podfile, then `pod install` + - **SPM**: Add Clix package to extension target in Xcode (General > Frameworks) +3. Implement NotificationService.swift: + ```swift + import UserNotifications + import Clix + + class NotificationService: ClixNotificationServiceExtension { + override func didReceive(_ request: UNNotificationRequest, + withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + register(projectId: "YOUR_PROJECT_ID") + super.didReceive(request, withContentHandler: contentHandler) + } + } + ``` +4. Add App Groups capability to both main app and extension (same group ID: `group.clix.{BUNDLE_ID}`) +5. For Xcode 15+: Set `ENABLE_USER_SCRIPT_SANDBOXING` to "No" in extension's Build Settings + +For detailed setup, run `clix ios-setup` or `/ios-setup` in interactive mode. + ## Output Format After completion, report: diff --git a/src/lib/skills/ios-setup/SKILL.md b/src/lib/skills/ios-setup/SKILL.md index 82914e5..f42786f 100644 --- a/src/lib/skills/ios-setup/SKILL.md +++ b/src/lib/skills/ios-setup/SKILL.md @@ -128,6 +128,61 @@ Create or modify entitlements files. Use Write/Edit tools for these operations. **Note:** Replace `{BUNDLE_ID}` with the actual bundle identifier (e.g., `com.example.myapp`). +### Phase 3.5: Notification Service Extension Setup + +Create a Notification Service Extension for rich push notifications (images, buttons, etc.). + +**Create Extension Target in Xcode:** +```text +1. File > New > Target +2. Select "Notification Service Extension" +3. Name it "{AppName}NotificationServiceExtension" (e.g., "MyAppNotificationServiceExtension") +4. Click "Finish" (Cancel the "Activate scheme" dialog) +5. Note: Use this exact name consistently in Podfile, entitlements path, and SPM setup +``` + +**Implement NotificationService.swift:** + +```swift +import UserNotifications +import Clix + +class NotificationService: ClixNotificationServiceExtension { + override func didReceive( + _ request: UNNotificationRequest, + withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void + ) { + register(projectId: "YOUR_PROJECT_ID") + super.didReceive(request, withContentHandler: contentHandler) + } +} +``` + +**Note:** Replace `YOUR_PROJECT_ID` with your actual Clix project ID from + +**Add Clix SDK to Extension Target:** + +For CocoaPods projects, add to Podfile: +```ruby +target '{AppName}NotificationServiceExtension' do + pod 'Clix' +end +``` +Then run: `cd ios && pod install` + +For SPM projects in Xcode: +1. Select the extension target +2. Go to General > Frameworks, Libraries, and Embedded Content +3. Click + and add the Clix package + +**Configure Build Settings (Xcode 15+):** + +For the extension target: +- Set `ENABLE_USER_SCRIPT_SANDBOXING` to "No" in Build Settings + +For React Native projects with Firebase: +- In Build Phases, move "Embed Foundation Extensions" above "[RNFB] Core Configuration" + ### Phase 4: Apple Developer Portal Configuration Guide user through manual portal configuration. These steps CANNOT be automated.