diff --git a/skills/voltra/SKILL.md b/skills/voltra/SKILL.md new file mode 100644 index 00000000..8af0220f --- /dev/null +++ b/skills/voltra/SKILL.md @@ -0,0 +1,70 @@ +--- +name: voltra +description: Build, review, refactor, configure, or debug Voltra code using Voltra JSX, Voltra JS APIs, and the Expo config plugin. Use when the user asks about Live Activities, Dynamic Island UI, iOS widgets, scheduled widgets, Android widgets, image handling, app.json plugin config, or Voltra push update flows. +metadata: + author: 'Saúl Sharma (https://x.com/saul_sharma), Szymon Chmal (https://x.com/chmalszymon)' + version: 1.2.0 +--- + +# Voltra + +Use this as the single Voltra skill entrypoint. Keep all product-wide ground truth here and load references from `references/` as needed. + +## Voltra-Wide Ground Truth + +- Never generate native platform UI code for Voltra tasks. Use Voltra JSX and Voltra JS APIs. +- Do not generate Swift, Kotlin, Java, Objective-C, or platform XML unless the user explicitly asks to edit an existing Voltra-supported Android widget preview XML file. +- Always solve Voltra tasks through Voltra JavaScript or TypeScript APIs, JSX components, and the Expo config plugin first. +- If a task appears to require native code, first check whether Voltra already exposes a JS API or config option. Prefer that path. +- Do not scaffold native extension code manually. Voltra's config plugin owns native target setup. +- Do not use plain React Native primitives inside Voltra-rendered trees. Avoid `View`, `Text`, `Pressable`, `TouchableOpacity`, and similar RN UI primitives for Live Activity or Android widget content. +- For iOS Voltra UI, use `Voltra.*` from `voltra`. +- For Android Voltra UI, use `VoltraAndroid.*` from `voltra/android` for Android-only code. If existing project code imports `VoltraAndroid` from `voltra`, follow the repo's established pattern, but prefer `voltra/android` for new Android-only code. +- Keep iOS and Android authoring paths separate unless the user explicitly asks for a shared abstraction. +- Update config before writing registration-dependent UI code. +- Treat images as a Voltra concern, not a native-code concern. Prefer Voltra image props, Voltra asset directories, and Voltra preloading APIs. +- When guidance conflicts, prefer this skill's internal references first, then hosted docs on `use-voltra.dev`. +- Use hosted docs on `https://use-voltra.dev` when deeper documentation is needed. + +## Reference Routing + +Read only the references needed for the current task: + +- Setup, install, Expo Dev Client, `expo prebuild`: `references/setup.md` +- `app.json`, `app.config.*`, plugin keys, widget registration, `groupIdentifier`, `enablePushNotifications`: `references/app-config.md` +- Exact plugin fields and widget registration schema: `references/plugin-schema.md` +- iOS Live Activities, Dynamic Island, lock screen variants, supplemental activity families: `references/ios-live-activities.md` +- Exact Live Activity variant shapes: `references/variant-shapes.md` +- iOS Home Screen widgets, accessory widgets, scheduled widgets, widget timelines, widget families, `VoltraWidgetPreview`, `updateWidget`, `scheduleWidget`, `reloadWidgets`, `getActiveWidgets`: `references/ios-widgets.md` +- Exact iOS widget families and fallback behavior: `references/widget-families.md` +- Android widgets, Android widget previews, pre-rendering, widget updates: `references/android-widgets.md` +- Android component choices and widget API checklist: `references/component-mapping.md`, `references/runtime-api-checklist.md` +- APNS, push tokens, push-to-start, channel IDs, server-rendered Live Activity payloads: `references/ios-server-updates.md` and usually `references/ios-live-activities.md` +- Exact APNS flow details: `references/push-flow.md` +- Image handling for Voltra surfaces: `references/images.md` plus the target surface reference + +## Working Style + +1. Identify the target platform and surface first. +2. Confirm the correct Voltra namespace and JS entrypoint. +3. Update config before writing registration-dependent UI code. +4. Read only the domain references needed for the task. +5. Use Voltra APIs that already exist in the repo before inventing new abstractions. +6. Keep answers scoped to the requested platform. + +## Reference Index + +- `references/source-of-truth.md` +- `references/images.md` +- `references/setup.md` +- `references/app-config.md` +- `references/plugin-schema.md` +- `references/ios-live-activities.md` +- `references/variant-shapes.md` +- `references/ios-widgets.md` +- `references/widget-families.md` +- `references/android-widgets.md` +- `references/component-mapping.md` +- `references/runtime-api-checklist.md` +- `references/ios-server-updates.md` +- `references/push-flow.md` diff --git a/skills/voltra/references/android-widgets.md b/skills/voltra/references/android-widgets.md new file mode 100644 index 00000000..e6ec7526 --- /dev/null +++ b/skills/voltra/references/android-widgets.md @@ -0,0 +1,31 @@ +# Android Widgets + +Use this reference for Android Voltra widget UI or Android widget runtime APIs. + +## Domain Rules + +- Use `VoltraAndroid` for Android Voltra UI. +- For new Android-only code, prefer `VoltraAndroid` from `voltra/android` and runtime APIs from `voltra/android/client`. +- Do not use `Voltra.VStack`, `Voltra.HStack`, or plain React Native primitives inside Android Voltra widget trees. +- Do not claim APNS or undocumented FCM server-update support for Android. +- If the task includes widget registration, picker previews, or initial state files, also read `app-config.md`. +- For images, use `VoltraAndroid.Image` with build-time `assetName`s or preloaded keys. Use `preloadImages`, `reloadWidgets`, and `clearPreloadedImages` from `voltra/android/client` for runtime images. + +## Preferred APIs + +- `updateAndroidWidget` +- `reloadAndroidWidgets` +- `clearAndroidWidget` +- `clearAllAndroidWidgets` +- `requestPinAndroidWidget` +- `getActiveWidgets` +- `VoltraWidgetPreview` +- `VoltraView` +- `preloadImages` +- `reloadWidgets` +- `clearPreloadedImages` + +## Sources + +- `component-mapping.md` +- `runtime-api-checklist.md` diff --git a/skills/voltra/references/app-config.md b/skills/voltra/references/app-config.md new file mode 100644 index 00000000..6534343d --- /dev/null +++ b/skills/voltra/references/app-config.md @@ -0,0 +1,25 @@ +# App Config + +Use this reference for Voltra plugin configuration. + +## Domain Rules + +- Update `app.json` or `app.config.*` before writing widget code that depends on registration, previews, or initial state files. +- For iOS push updates, require `enablePushNotifications: true`. +- For Android widgets, define them under `android.widgets` in the Voltra plugin config. +- Only mention preview XML when the user is explicitly editing an existing Android widget preview layout supported by Voltra. +- Do not invent unsupported plugin keys. +- If the task is about iOS image preloading, check whether `groupIdentifier` is needed for the intended Voltra surface and storage flow. + +## Working Rules + +- iOS-oriented plugin keys live at the top level of the Voltra plugin config. +- Android widget registration lives under `android.widgets`. +- Use `groupIdentifier` when the app needs extension data sharing or forwarded interactions. +- If the task includes iOS widget UI or `supportedFamilies`, also read `ios-widgets.md`. +- If the task includes Android widget UI, also read `android-widgets.md`. +- If the task includes iOS server updates, also read `ios-server-updates.md`. + +## Sources + +- `plugin-schema.md` diff --git a/skills/voltra/references/component-mapping.md b/skills/voltra/references/component-mapping.md new file mode 100644 index 00000000..a50d3e0c --- /dev/null +++ b/skills/voltra/references/component-mapping.md @@ -0,0 +1,31 @@ +# Component Mapping + +Prefer these Android Voltra primitives over iOS or React Native UI primitives: + +- `VoltraAndroid.Column` instead of `Voltra.VStack` +- `VoltraAndroid.Row` instead of `Voltra.HStack` +- `VoltraAndroid.Box` instead of layered RN `View` trees +- `VoltraAndroid.Text` instead of RN `Text` +- `VoltraAndroid.Image` instead of RN `Image` +- `VoltraAndroid.Scaffold` for top-level Android widget layouts +- `VoltraAndroid.Spacer` for spacing +- Android-specific controls when needed: + - `Button` + - `FilledButton` + - `OutlineButton` + - `CircleIconButton` + - `SquareIconButton` + - `Switch` + - `CheckBox` + - `RadioButton` + +Avoid these in Android Voltra UI: + +- `Voltra.VStack` +- `Voltra.HStack` +- RN `View` +- RN `Text` +- RN `Pressable` +- Native Glance/Kotlin implementations + +Hosted docs: see `source-of-truth.md`. diff --git a/skills/voltra/references/images.md b/skills/voltra/references/images.md new file mode 100644 index 00000000..ea921aa3 --- /dev/null +++ b/skills/voltra/references/images.md @@ -0,0 +1,50 @@ +# Images + +Voltra supports three image paths: + +- build-time assets +- runtime preloading +- base64 for very small generated images + +## Build-Time Assets + +Use build-time assets when the image is known at build time. + +- iOS: place files under `assets/voltra/` +- Android: place files under `assets/voltra-android/` + +Reference bundled assets with `assetName`. + +Examples: + +- iOS: `` +- Android: `` + +Android notes: + +- Android resource names are sanitized to lowercase underscore names. +- Do not include the file extension in Android `assetName`. + +## Runtime Preloading + +Use preloading when the image comes from a remote URL or runtime data. + +- iOS preloading API: `preloadImages`, `reloadLiveActivities`, `clearPreloadedImages` from `voltra/client` +- Android preloading API: `preloadImages`, `reloadWidgets`, `clearPreloadedImages` from `voltra/android/client` + +After preloading, reference the image with the same `key` via `assetName`. + +## Platform Rules + +- iOS Live Activities and iOS widgets use `Voltra.Image`. +- Android widgets and Android live updates use `VoltraAndroid.Image`. +- iOS image preloading depends on App Group-backed shared storage, so config tasks may also need `groupIdentifier`. +- Android image preloading uses app cache plus Voltra's local delivery path; do not invent a native image pipeline. + +## Base64 + +Use base64 only for very small inline images. Prefer build-time assets or preloading for anything non-trivial. + +## Sources + +- `source-of-truth.md` diff --git a/skills/voltra/references/ios-live-activities.md b/skills/voltra/references/ios-live-activities.md new file mode 100644 index 00000000..e95a4b71 --- /dev/null +++ b/skills/voltra/references/ios-live-activities.md @@ -0,0 +1,27 @@ +# iOS Live Activities + +Use this reference for iOS Live Activity UI or lifecycle APIs. + +## Domain Rules + +- Use `Voltra` from `voltra` for Live Activity UI trees. +- Use `voltra/client` for runtime APIs such as `useLiveActivity`, `startLiveActivity`, `updateLiveActivity`, `stopLiveActivity`, and Voltra event listeners. +- Do not use `VoltraAndroid` or Android widget primitives in iOS Live Activity code. +- Use valid iOS variant keys: `lockScreen`, `island`, and `supplementalActivityFamilies`. +- For images, use `Voltra.Image` with either a bundled `assetName` or a preloaded image key. Use `preloadImages` and `reloadLiveActivities` from `voltra/client` for runtime images. +- If the task involves APNS, push tokens, push-to-start, channel IDs, or backend-driven updates, also read `ios-server-updates.md`. + +## Preferred APIs + +- `useLiveActivity` +- `startLiveActivity` +- `updateLiveActivity` +- `stopLiveActivity` +- `endAllLiveActivities` +- `addVoltraListener` +- `VoltraView` +- `VoltraLiveActivityPreview` + +## Sources + +- `variant-shapes.md` diff --git a/skills/voltra/references/ios-server-updates.md b/skills/voltra/references/ios-server-updates.md new file mode 100644 index 00000000..e8dc9b8f --- /dev/null +++ b/skills/voltra/references/ios-server-updates.md @@ -0,0 +1,25 @@ +# iOS Server Updates + +Use this reference for APNS-driven Live Activity updates. + +## Domain Rules + +- This flow is iOS-only. +- Require `enablePushNotifications: true` in the Voltra plugin config. +- Use Voltra event APIs from `voltra/client` to collect tokens. +- Use `voltra/server` to render Live Activity payloads. +- Use Voltra-generated UI JSON in APNS payloads. +- Do not extrapolate this APNS flow to Android unless Voltra provides a documented JS API and guide for that exact use case. +- If the task also defines or changes Live Activity UI, also read `ios-live-activities.md`. + +## Preferred APIs + +- `addVoltraListener` +- `startLiveActivity` +- `useLiveActivity` +- `renderLiveActivityToString` +- `Voltra` from `voltra/server` + +## Sources + +- `push-flow.md` diff --git a/skills/voltra/references/ios-widgets.md b/skills/voltra/references/ios-widgets.md new file mode 100644 index 00000000..7ee783cf --- /dev/null +++ b/skills/voltra/references/ios-widgets.md @@ -0,0 +1,28 @@ +# iOS Widgets + +Use this reference for iOS widget UI, scheduled widgets, widget families, or iOS widget runtime APIs. + +## Domain Rules + +- Use `Voltra` from `voltra` for iOS widget UI trees. +- Use `voltra/client` for iOS widget APIs such as `updateWidget`, `scheduleWidget`, `reloadWidgets`, `clearWidget`, `clearAllWidgets`, `getActiveWidgets`, and `VoltraWidgetPreview`. +- Do not use `VoltraAndroid` or Android widget primitives in iOS widget code. +- Widget registration lives in the Voltra plugin config. If the task includes `widgets`, `supportedFamilies`, or `initialStatePath`, also read `app-config.md`. +- `VoltraWidgetPreview` is a React Native preview component for app screens, not a Voltra widget primitive to nest inside widget JSX. +- Use `scheduleWidget` for timeline-based or scheduled widget updates instead of inventing background schedulers or native WidgetKit code. +- For images, use `Voltra.Image` with bundled `assetName`s or preloaded keys. If shared image resources change, use `reloadWidgets`. + +## Preferred APIs + +- `VoltraWidgetPreview` +- `updateWidget` +- `scheduleWidget` +- `reloadWidgets` +- `clearWidget` +- `clearAllWidgets` +- `getActiveWidgets` +- `WidgetFamily` + +## Sources + +- `widget-families.md` diff --git a/skills/voltra/references/plugin-schema.md b/skills/voltra/references/plugin-schema.md new file mode 100644 index 00000000..24d48499 --- /dev/null +++ b/skills/voltra/references/plugin-schema.md @@ -0,0 +1,62 @@ +# Plugin Schema + +Voltra plugin config lives under `expo.plugins`. + +## Common Top-Level Keys + +- `groupIdentifier` +- `enablePushNotifications` +- `liveActivity` +- `widgets` +- `fonts` +- `android` +- `deploymentTarget` +- `targetName` + +## iOS Widget Schema + +Use top-level `widgets` for iOS widget gallery registration. + +- `id`: unique identifier, use alphanumeric and underscores only +- `displayName` +- `description` +- `supportedFamilies`: array of iOS families such as `systemSmall`, `systemMedium`, `systemLarge` +- `initialStatePath` + +Other important Apple-side keys: + +- `groupIdentifier`: needed for shared storage, forwarded interactions, and image preloading +- `enablePushNotifications`: required for APNS-driven Live Activity updates +- `deploymentTarget`: widget extension deployment target +- `targetName`: custom Apple widget extension target name + +## Android Widget Schema + +Use `android.widgets` for Android widget registration. + +- `id`: unique identifier, use alphanumeric and underscores only +- `displayName` +- `description` +- `targetCellWidth` +- `targetCellHeight` +- `minCellWidth` +- `minCellHeight` +- `minWidth` +- `minHeight` +- `resizeMode` +- `widgetCategory` +- `initialStatePath` +- `previewImage` +- `previewLayout` + +## Decision Rules + +- If the task asks for Apple widget gallery registration or `supportedFamilies`, stay in config first and then read `ios-widgets.md`. +- If the task asks for Android widget picker metadata, stay in config first and then read `android-widgets.md`. +- If the task asks for pre-rendered initial widget content, add `initialStatePath` and then move to the target widget reference. +- If the task asks for APNS-driven Live Activity updates, ensure `enablePushNotifications` is present and then move to `ios-server-updates.md`. +- If the task asks for iOS image preloading or shared extension images, check `groupIdentifier` before moving on to UI code. + +## Hosted Docs + +Consult `source-of-truth.md` for the canonical hosted doc list. diff --git a/skills/voltra/references/push-flow.md b/skills/voltra/references/push-flow.md new file mode 100644 index 00000000..2e84758f --- /dev/null +++ b/skills/voltra/references/push-flow.md @@ -0,0 +1,27 @@ +# Push Flow + +Use this flow for iOS Live Activity server-driven updates: + +1. Enable `enablePushNotifications: true` in the Voltra plugin config. +2. Start the Live Activity or subscribe to token events in the app. +3. Capture Voltra push tokens with `addVoltraListener` from `voltra/client`. +4. Send the token or channel identifier to your backend. +5. Render the Live Activity UI payload with `renderLiveActivityToString` from `voltra/server`. +6. Send the APNS request with the Voltra-generated UI JSON in the payload. + +Important concepts: + +- Update token: update an existing Live Activity. +- Push-to-start token: start a Live Activity remotely. +- `channelId`: subscribe to broadcast updates on supported iOS versions. +- APNS headers must match Live Activity requirements. +- Keep payloads small. + +Use these sources first: + +- `source-of-truth.md` +- `https://use-voltra.dev/ios/development/server-side-updates` +- `https://use-voltra.dev/ios/development/events` +- `https://use-voltra.dev/ios/api/configuration` + +Do not extend this flow to Android unless new repo docs and APIs clearly support it. diff --git a/skills/voltra/references/runtime-api-checklist.md b/skills/voltra/references/runtime-api-checklist.md new file mode 100644 index 00000000..d560519e --- /dev/null +++ b/skills/voltra/references/runtime-api-checklist.md @@ -0,0 +1,23 @@ +# Runtime API Checklist + +Use Android-specific Voltra widget APIs when possible. + +Widget runtime entrypoint: + +- `voltra/android/client` + +Use these for widgets: + +- `updateAndroidWidget` +- `reloadAndroidWidgets` +- `clearAndroidWidget` +- `clearAllAndroidWidgets` +- `requestPinAndroidWidget` +- `getActiveWidgets` +- `VoltraWidgetPreview` +- `VoltraView` +- `preloadImages` +- `reloadWidgets` +- `clearPreloadedImages` + +Do not claim a full Android server-push architecture unless the task is directly supported by current Voltra JS APIs and docs. diff --git a/skills/voltra/references/setup.md b/skills/voltra/references/setup.md new file mode 100644 index 00000000..a406b510 --- /dev/null +++ b/skills/voltra/references/setup.md @@ -0,0 +1,23 @@ +# Setup + +Use this reference when the task is about bootstrapping or installation. + +## Domain Rules + +- Voltra is not supported in Expo Go. Use Expo Dev Client or a native build. +- Start with the Voltra package, Expo config plugin, and `expo prebuild`. +- If setup also requires widget registration or push settings, also read `app-config.md`. + +## Setup Flow + +1. Install `voltra`. +2. Add the Voltra plugin to `app.json` or `app.config.*`. +3. For iOS, ensure the deployment target meets Voltra's minimum supported version. +4. Run `expo prebuild` for the target platform. +5. Continue with the relevant platform reference. + +## Sources + +- `source-of-truth.md` +- `https://use-voltra.dev/ios/setup` +- `https://use-voltra.dev/android/setup` diff --git a/skills/voltra/references/source-of-truth.md b/skills/voltra/references/source-of-truth.md new file mode 100644 index 00000000..70e8965e --- /dev/null +++ b/skills/voltra/references/source-of-truth.md @@ -0,0 +1,32 @@ +# Source Of Truth + +Use this file as the compact local source of truth for Voltra behavior. For deeper documentation, use hosted docs on `use-voltra.dev`. + +Hosted docs to use for guidance: + +- `https://use-voltra.dev/ios/setup` +- `https://use-voltra.dev/android/setup` +- `https://use-voltra.dev/ios/development/developing-live-activities` +- `https://use-voltra.dev/ios/development/developing-widgets` +- `https://use-voltra.dev/ios/development/images` +- `https://use-voltra.dev/ios/development/image-preloading` +- `https://use-voltra.dev/ios/development/server-side-updates` +- `https://use-voltra.dev/android/development/developing-widgets` +- `https://use-voltra.dev/android/development/images` +- `https://use-voltra.dev/android/development/image-preloading` +- `https://use-voltra.dev/android/api/plugin-configuration` + +Core facts: + +- iOS UI namespace: `Voltra` from `voltra` +- Android UI namespace for Android-only code: `VoltraAndroid` from `voltra/android` +- iOS runtime API entrypoint: `voltra/client` +- iOS server rendering entrypoint: `voltra/server` +- Android runtime API entrypoint: `voltra/android/client` +- Android-only package entrypoints exist: `voltra/android`, `voltra/android/client`, `voltra/android/server` + +Default rule: + +- For new Android-only code, prefer `voltra/android` and `voltra/android/client`. +- If existing project code already uses `VoltraAndroid` from `voltra`, matching that local pattern can be acceptable for consistency. +- Use `use-voltra.dev` for documentation lookups. diff --git a/skills/voltra/references/variant-shapes.md b/skills/voltra/references/variant-shapes.md new file mode 100644 index 00000000..09971916 --- /dev/null +++ b/skills/voltra/references/variant-shapes.md @@ -0,0 +1,43 @@ +# Variant Shapes + +Use these iOS Live Activity shapes. + +## Minimal lock screen only + +```tsx +const variants = { + lockScreen: Hello, +} +``` + +## Dynamic Island shape + +```tsx +const variants = { + island: { + minimal: M, + compact: { + leading: L, + trailing: T, + }, + expanded: { + leading: L, + trailing: T, + center: C, + bottom: B, + }, + }, +} +``` + +## Supplemental families + +```tsx +const variants = { + supplementalActivityFamilies: { + small: ETA 12 min, + }, +} +``` + +Hosted docs: see `source-of-truth.md`. diff --git a/skills/voltra/references/widget-families.md b/skills/voltra/references/widget-families.md new file mode 100644 index 00000000..ee7f7f2a --- /dev/null +++ b/skills/voltra/references/widget-families.md @@ -0,0 +1,29 @@ +# Widget Families + +Use these iOS widget families when defining `WidgetVariants`: + +- `systemSmall` +- `systemMedium` +- `systemLarge` +- `systemExtraLarge` +- `accessoryCircular` +- `accessoryRectangular` +- `accessoryInline` + +Working rules: + +- Build widget content with `Voltra.*` components. +- Use `VoltraWidgetPreview` from `voltra/client` to preview widget content in React Native screens. +- Use `updateWidget` for immediate updates. +- Use `scheduleWidget` for timeline-based or scheduled widget updates. This is the correct Voltra API for predictable future widget content changes on iOS. +- Use `Voltra.Image` for widget images. Bundled assets and preloaded image keys are both referenced through `assetName`. +- Use `reloadWidgets` after changing shared resources such as preloaded images. +- Use `getActiveWidgets` to inspect installed widget instances. + +Plugin reminder: + +- iOS widget registration is configured in the Voltra plugin under `widgets`. +- `supportedFamilies` controls the sizes exposed in the widget gallery. +- If registration or family support changes are part of the task, also read `app-config.md`. + +Hosted docs: see `source-of-truth.md`.