Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions skills/voltra/SKILL.md
Original file line number Diff line number Diff line change
@@ -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`
31 changes: 31 additions & 0 deletions skills/voltra/references/android-widgets.md
Original file line number Diff line number Diff line change
@@ -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`
25 changes: 25 additions & 0 deletions skills/voltra/references/app-config.md
Original file line number Diff line number Diff line change
@@ -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`
31 changes: 31 additions & 0 deletions skills/voltra/references/component-mapping.md
Original file line number Diff line number Diff line change
@@ -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`.
50 changes: 50 additions & 0 deletions skills/voltra/references/images.md
Original file line number Diff line number Diff line change
@@ -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: `<Voltra.Image source={{ assetName: 'logo.png' }} />`
- Android: `<VoltraAndroid.Image source={{ assetName: 'logo' }} />`

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`
27 changes: 27 additions & 0 deletions skills/voltra/references/ios-live-activities.md
Original file line number Diff line number Diff line change
@@ -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`
25 changes: 25 additions & 0 deletions skills/voltra/references/ios-server-updates.md
Original file line number Diff line number Diff line change
@@ -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`
28 changes: 28 additions & 0 deletions skills/voltra/references/ios-widgets.md
Original file line number Diff line number Diff line change
@@ -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`
62 changes: 62 additions & 0 deletions skills/voltra/references/plugin-schema.md
Original file line number Diff line number Diff line change
@@ -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.
27 changes: 27 additions & 0 deletions skills/voltra/references/push-flow.md
Original file line number Diff line number Diff line change
@@ -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.
Loading
Loading