expo-modules — android expo-modules, apple-health, community, android, ide skills, apple-health-analytics, apple-health-xml, capacitor-android, data-sync, health, Claude Code

v1.0.0

이 스킬 정보

iOS에서 Apple HealthKit과 무결점 통합이 필요한 모바일 헬스 에이전트에 적합 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

# Core Topics

manavkushwaha10 manavkushwaha10
[0]
[0]
Updated: 3/23/2026

Killer-Skills Review

Decision support comes first. Repository text comes second.

Reference-Only Page Review Score: 7/11

This page remains useful for operators, but Killer-Skills treats it as reference material instead of a primary organic landing page.

Original recommendation layer Concrete use-case guidance Explicit limitations and caution
Review Score
7/11
Quality Score
42
Canonical Locale
en
Detected Body Locale
en

iOS에서 Apple HealthKit과 무결점 통합이 필요한 모바일 헬스 에이전트에 적합 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

이 스킬을 사용하는 이유

에이전트가 네이티브 API를 사용하여 건강 데이터를 읽고, 쓰고, 구독할 수 있는 능력을 부여하며, `std:kv-storage`와 같은 표준을 통해 다양한 건강 메트릭과 운동을 지원하고 네이티브 기능을 직접 노출

최적의 용도

iOS에서 Apple HealthKit과 무결점 통합이 필요한 모바일 헬스 에이전트에 적합

실행 가능한 사용 사례 for expo-modules

Apple HealthKit와 상호 작용하여 피트니스 추적을 수행
건강 데이터 업데이트를 구독하여 개인화된 추천을 받기
iOS 건강 메트릭에 직접 액세스하여 네이티브 건강 및 피트니스 애플리케이션 개발

! 보안 및 제한 사항

  • iOS만 해당
  • 네이티브 API 호환성이 필요
  • Apple HealthKit의 가용성과 사용자 권한에 의존

Why this page is reference-only

  • - Current locale does not satisfy the locale-governance contract.
  • - The underlying skill quality score is below the review floor.

Source Boundary

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is expo-modules?

iOS에서 Apple HealthKit과 무결점 통합이 필요한 모바일 헬스 에이전트에 적합 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

How do I install expo-modules?

Run the command: npx killer-skills add manavkushwaha10/apple-health/expo-modules. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for expo-modules?

Key use cases include: Apple HealthKit와 상호 작용하여 피트니스 추적을 수행, 건강 데이터 업데이트를 구독하여 개인화된 추천을 받기, iOS 건강 메트릭에 직접 액세스하여 네이티브 건강 및 피트니스 애플리케이션 개발.

Which IDEs are compatible with expo-modules?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for expo-modules?

iOS만 해당. 네이티브 API 호환성이 필요. Apple HealthKit의 가용성과 사용자 권한에 의존.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add manavkushwaha10/apple-health/expo-modules. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use expo-modules immediately in the current project.

! Reference-Only Mode

This page remains useful for installation and reference, but Killer-Skills no longer treats it as a primary indexable landing page. Read the review above before relying on the upstream repository instructions.

Imported Repository Instructions

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

Supporting Evidence

expo-modules

Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

SKILL.md
Readonly
Imported Repository Instructions
The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.
Supporting Evidence

Great module standards

  • Design native APIs as if you contributing W3C specs for the browser, take inspiration from modern web modules. eg std:kv-storage, clipboard.
  • Aim for 100% backwards compatibility like the web.
  • Create escape hatches for single-platform functionality.
  • Avoid extraneous abstractions. Directly expose native functionality.
  • Avoid unnecessary async methods. Use sync methods when possible.
  • Prefer string union types for API options instead of boolean flags, enums, or multiple parameters. eg instead of capture(options: { isHighQuality: boolean }), use capture(options: { quality: 'high' | 'medium' | 'low' }).
  • Marshalling is awesome for platform-specific APIs.
  • New Architecture only. NEVER support legacy React Native architecture.
  • ALWAYS use only Expo modules API.
  • Prefer Swift and Kotlin.
  • Use optionality for availability checks as opposed to extraneous isAvailable functions or constants. eg snapshot.capture?.() instead of snapshot.isAvailable && snapshot.capture().
  • ALWAYS support the latest and greatest API features.

Example of a GREAT Expo module:

ts
1import { NativeModule } from "expo"; 2 3declare class AppClipModule extends NativeModule<{}> { 4 prompt(): void; 5 isAppClip?: boolean; 6} 7 8// This call loads the native module object from the JSI. 9const AppClipNative = 10 typeof expo !== "undefined" 11 ? (expo.modules.AppClip as AppClipModule) ?? {} 12 : {}; 13 14if (AppClipNative?.isAppClip) { 15 navigator.appClip = { 16 prompt: AppClipNative.prompt, 17 }; 18} 19 20// Add types for the global `navigator.appClip` object. 21declare global { 22 interface Navigator { 23 /** 24 * Only available in an App Clip context. 25 * @expo 26 */ 27 appClip?: { 28 /** Open the SKOverlay */ 29 prompt: () => void; 30 }; 31 } 32} 33 34export {};
  • Simple web-style interface.
  • Global type augmentation for easy access.
  • Docs in the type definitions.
  • Optional availability checks instead of extraneous isAvailable methods.

Example of a POOR Expo module:

ts
1import { NativeModulesProxy } from "expo-modules-core"; 2const { ExpoAppClip } = NativeModulesProxy; 3export default { 4 promptAppClip() { 5 return ExpoAppClip.promptAppClip(); 6 }, 7 isAppClipAvailable() { 8 return ExpoAppClip.isAppClipAvailable(); 9 }, 10};

Great documentation

  • If you have a function like isAvailable(), explain why it exists in the docs. Research cases where it may return false such as in a simulator or particular OS version.
  • Document OS version availability for functions and constants in the type definitions.

BAD module standards

  • APIs that are hard to import, e.g. import * as MediaLibrary from 'expo-media-library'; instead of import { MediaLibrary } from 'expo/media';
  • Extraneous abstractions over native functionality. The native module is installing on the global, do not wrap it in another layer for no reason.
  • Extraneous async methods when sync methods are possible.
  • Boolean flags instead of string union types for options.
  • Supporting legacy React Native architecture.

Views

Take API inspiration from great web component libraries like BaseUI and Radix.

Consider if you're building a control or a display component. Controls should have more interactive APIs, while display components should be more declarative.

Prefer functions on views instead of useImperativeHandle + findNodeHandle.

swift
1AsyncFunction("capture") { (view, options: Options) -> Ref in 2 return try capture(self.appContext, view) 3}

Remember to export views in the module:

swift
1import ExpoModulesCore 2 3public class ExpoWebViewModule: Module { 4 public func definition() -> ModuleDefinition { 5 Name("ExpoWebView") 6 7 View(ExpoWebView.self) {} 8 } 9}

Marshalling-style API

Consider this example https://github.com/EvanBacon/expo-shared-objects-haptics-example/blob/be90e92f8dba9b0807009502ab25c423c57e640d/modules/my-module/ios/MyModule.swift#L1C1-L178C2

Using @retroactive Convertible and AnyArgument to convert between Swift types and dictionaries enables passing complex data structures across the boundary without writing custom serialization code for each type.

swift
1extension CHHapticEventParameter: @retroactive Convertible, AnyArgument { 2 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 3 guard let dict = value as? [String: Any], 4 let parameterIDRaw = dict["parameterID"] as? String, 5 let value = dict["value"] as? Double else { 6 throw NotADictionaryException() 7 } 8 return Self(parameterID: CHHapticEvent.ParameterID(rawValue: parameterIDRaw), value: Float(value)) 9 } 10} 11 12extension CHHapticEvent: @retroactive Convertible, AnyArgument { 13 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 14 guard let dict = value as? [String: Any], 15 let eventTypeRaw = dict["eventType"] as? String, 16 let relativeTime = dict["relativeTime"] as? Double else { 17 throw NotADictionaryException() 18 } 19 let eventType = CHHapticEvent.EventType(rawValue: eventTypeRaw) 20 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticEventParameter? in 21 try? CHHapticEventParameter.convert(from: paramDict, appContext: appContext) 22 } ?? [] 23 return Self(eventType: eventType, parameters: parameters, relativeTime: relativeTime) 24 } 25} 26 27extension CHHapticDynamicParameter: @retroactive Convertible, AnyArgument { 28 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 29 guard let dict = value as? [String: Any], 30 let parameterIDRaw = dict["parameterID"] as? String, 31 let value = dict["value"] as? Double, 32 let relativeTime = dict["relativeTime"] as? Double else { 33 throw NotADictionaryException() 34 } 35 36 return Self(parameterID: CHHapticDynamicParameter.ID(rawValue: parameterIDRaw), value: Float(value), relativeTime: relativeTime) 37 } 38} 39 40extension CHHapticPattern: @retroactive Convertible, AnyArgument { 41 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 42 guard let dict = value as? [String: Any], 43 let eventsArray = dict["events"] as? [[String: Any]] else { 44 throw NotADictionaryException() 45 } 46 let events = try eventsArray.map { eventDict -> CHHapticEvent in 47 try CHHapticEvent.convert(from: eventDict, appContext: appContext) 48 } 49 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticDynamicParameter? in 50 return try? CHHapticDynamicParameter.convert(from: paramDict, appContext: appContext) 51 } ?? [] 52 return try Self(events: events, parameters: parameters) 53 } 54} 55 56internal final class NotAnArrayException: Exception { 57 override var reason: String { 58 "Given value is not an array" 59 } 60} 61 62internal final class IncorrectArraySizeException: GenericException<(expected: Int, actual: Int)> { 63 override var reason: String { 64 "Given array has unexpected number of elements: \(param.actual), expected: \(param.expected)" 65 } 66} 67 68internal final class NotADictionaryException: Exception { 69 override var reason: String { 70 "Given value is not a dictionary" 71 } 72} 73

Later this can be used to implement methods that accept complex data structures as arguments.

swift
1Function("playPattern") { (pattern: CHHapticPattern) in 2 let player = try hapticEngine.makePlayer(with: pattern) 3 try player.start(atTime: 0) 4}

Use shorthand where possible, especially when the JS value matches the Swift value:

swift
1Property("__typename") { $0.__typename }

Shared objects

Shared objects are long-lived native instances that are shared to JS. They can be used to keep heavy state objects, such as a decoded bitmap, alive across React components, rather than spinning up a new native instance every time a component mounts.

Interacting with AppDelegate

To interact with HealthKit, the module may need to respond to app lifecycle events. This can be done by implementing the ExpoAppDelegateSubscriber protocol.

swift
1import ExpoModulesCore 2 3public class ExpoHeadAppDelegateSubscriber: ExpoAppDelegateSubscriber { 4 5// Any AppDelegate methods you want to implement 6 public func application( 7 _ application: UIApplication, 8 continue userActivity: NSUserActivity, 9 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void 10 ) -> Bool { 11 launchedActivity = userActivity 12 13 // ... 14 15 return false 16 } 17}

Then add the subscriber to the expo-module.config.json:

json
1{ 2 "platforms": ["apple", "android", "web"], 3 "apple": { 4 "modules": ["ExpoHeadModule", ...], 5 "appDelegateSubscribers": ["ExpoHeadAppDelegateSubscriber"] 6 } 7}

Expo ecosystem integration

Verification

  • Run yarn expo run:ios --no-bundler in an Expo app to headlessly compile the module and verify there are no compilation errors.

관련 스킬

Looking for an alternative to expo-modules or another community skill for your workflow? Explore these related open-source skills.

모두 보기

openclaw-release-maintainer

Logo of openclaw
openclaw

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

333.8k
0
인공지능

widget-generator

Logo of f
f

prompts.chat 피드 시스템을 위한 사용자 지정 가능한 위젯 플러그인을 생성합니다

149.6k
0
인공지능

flags

Logo of vercel
vercel

리액트 프레임워크

138.4k
0
브라우저

pr-review

Logo of pytorch
pytorch

파이썬에서 텐서와 동적 신경망 구현 및 강력한 GPU 가속 지원

98.6k
0
개발자