OpenClix Init
Purpose
This skill adds OpenClix functionality by copying client code into the user project, not by installing an SDK package.
Use a local-source integration model (shadcn-style): copy, adapt, wire, verify.
Core Rules
- Detect the real platform first using project files.
- Prioritize minimal edits to existing user code.
- Keep all OpenClix files in a dedicated namespace/directory.
- When creating local planning/report artifacts under , ensure is listed in (add it if missing).
- Reuse existing dependencies whenever possible.
- Do not add or update dependencies without explicit user approval.
- Run a build after integration and fix only integration-caused issues.
- Do not use in-memory fallback in production integration paths.
Platform Detection
Use file evidence in this order:
| Priority | Platform | Required Evidence |
|---|
| 1 | Expo | or with |
| 2 | React Native | with and typical + structure |
| 3 | Flutter | with Flutter SDK |
| 4 | iOS native | or or |
| 5 | Android native | or |
If signals conflict, trust concrete file evidence and report the mismatch.
Template Selection
- Expo / React Native:
- Flutter:
- iOS:
- Android: (package namespace )
is the canonical reference when platform ports need alignment.
Integration Workflow
- Identify platform and current startup/event/lifecycle entry points.
- Copy the selected template into a dedicated OpenClix area in the user project.
- Wire only required touchpoints:
- initialization at app startup
- event tracking call path
- foreground/app lifecycle trigger
- Keep existing architecture and code style intact; avoid broad refactors.
- Validate against
references/openclix.schema.json
when config/schema changes are involved.
Adapter Selection Rules
Select adapters using existing dependencies only:
- Choose concrete adapters at integration time; avoid runtime dependency auto-detection.
- If the project already has a supported persistent storage dependency, wire that implementation.
- If notification libraries already exist, wire the matching scheduler adapter.
- If no compatible dependency exists, fail fast with a clear integration error.
- Keep degraded in-memory paths out of production template defaults.
React Native / Expo storage selection:
- AsyncStorage project: use
AsyncStorageCampaignStateRepository
.
- MMKV project: use
MmkvCampaignStateRepository
.
- If both exist, prefer the project standard and copy only one storage adapter into the app.
- Inject explicitly when calling .
React Native / Expo scheduler selection:
- Notifee project: create
new NotifeeScheduler(notifee)
.
- Expo notifications project: create
new ExpoNotificationScheduler(ExpoNotifications)
.
- Inject explicitly when calling .
Platform expectations:
- React Native / Expo:
- Do not use runtime adapter auto-detection in core.
- Select storage/scheduler implementations during integration and inject dependencies explicitly.
- If compatible implementations are unavailable, initialization must fail with clear instructions.
- Flutter:
- Use callback-based scheduler adapter for existing notification plugin
- Require an explicit scheduler and state repository dependency at initialization
- iOS / Android native:
- Use platform-native implementations by default
- Do not introduce in-memory/no-op fallback as the default runtime behavior
Notification Permission and Foreground Setup
Notification permission must be requested before campaign triggers fire. Each platform template includes a permission utility; the integration agent must wire it at the appropriate location in the host app.
React Native / Expo — Permission
- Notifee projects: Import from
infrastructure/NotifeeNotificationSetup
. Call it at app startup (e.g. in or a startup hook) passing the Notifee adapter. No foreground handler is needed — Notifee handles foreground display natively via .
- Expo projects: Import and
setupExpoForegroundHandler
from infrastructure/ExpoNotificationSetup
. Call setupExpoForegroundHandler
once during initialization, then call at app startup.
iOS — Permission and Foreground Display
- Permission: Call
await NotificationPermission.request()
at app startup (e.g. in application(_:didFinishLaunchingWithOptions:)
or a SwiftUI modifier). This calls UNUserNotificationCenter.requestAuthorization
.
- Foreground display: iOS suppresses notification banners when the app is active. The template provides
ForegroundNotificationHandler.handleWillPresent(notification:completionHandler:)
as a static method.
- Critical: iOS allows only ONE
UNUserNotificationCenterDelegate
per app. Do NOT assign ForegroundNotificationHandler
as the delegate. Instead, set the app's existing delegate (usually ) as UNUserNotificationCenter.current().delegate = self
, and call the static method from the delegate's implementation.
Android — Permission
- Manifest: Add
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
to .
- Runtime request: On API 33+ (Android 13), call
NotificationPermission.shouldRequestPermission(context)
at startup. If it returns , use the Activity's or to request NotificationPermission.getPermissionString()
.
- Android does NOT need foreground display setup —
NotificationManager.notify()
always displays regardless of app state.
Flutter — Permission and Foreground Display
The
class in
notification/notification_permission.dart
accepts callbacks. Wire the host app's notification plugin:
- Provide a callback that calls the plugin's permission request API.
- Provide a callback that checks current status.
- Optionally provide a callback to configure foreground display (required for iOS, not needed for Android).
- Call at app startup before campaign triggers fire.
- Call
permission.setupForeground()
during initialization if the handler is provided.
Directory and Namespace Policy
OpenClix files must stay grouped in a dedicated location:
- React Native / Expo:
- Flutter:
- iOS: or
- Android:
app/src/main/kotlin/ai/openclix/
with packages
Dependency Policy
Before changing dependencies:
- Check what the selected template expects.
- Check what the user project already has.
- Prefer existing project libraries or platform APIs.
- If replacement is possible, adapt template code instead of adding dependencies.
- If no safe replacement exists, ask for approval before any dependency add/update.
Never run package-manager install/update commands without approval.
Build Verification
After wiring, run platform-appropriate build/analysis commands based on detected project structure.
Prefer project-native commands first (existing scripts, Gradle tasks, Xcode scheme, Flutter workflow).
If unclear, use common fallback commands:
- React Native / Expo:
- Android:
- iOS:
xcodebuild -scheme <scheme> build
or
- Flutter:
If build fails, apply minimal targeted fixes and retry. Stop only on hard blockers.
Completion Checklist
- OpenClix code added under dedicated namespace/directory.
- Existing app code changes are minimal and localized.
- No unapproved dependency additions or upgrades.
- Adapter wiring prefers existing dependencies and fails fast when unavailable.
- Build verification executed.
- Any remaining blockers clearly reported.