This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Expo Superwall SDK is an official Expo integration for Superwall, providing in-app paywall functionality for React Native applications. The project offers two SDK approaches:
- Hooks-based SDK (recommended for new projects): Modern React hooks interface
- Compat SDK (
expo-superwall/compat): Legacy compatibility layer for migrating from React Native Superwall SDK
Requirements: Expo SDK 53+ only. For older versions, users should use the legacy React Native SDK.
# Build the module
expo-module build
# Clean build artifacts
expo-module clean
# Run linting
expo-module lint
# Run tests
expo-module test
# Format code with Biome
biome check --write .
# Prepare for publishing
expo-module prepare
expo-module prepublishOnly# Open iOS project in Xcode
xed example/ios
# Open Android project in Android Studio
open -a "Android Studio" example/android
# Run on iOS
expo run:ios
# Run on Android
expo run:android# Version bump using changesets
changeset version
# Build and publish
yarn build && changeset publishThe SDK bridges TypeScript/React Native with native iOS (Swift) and Android (Kotlin) SDKs:
iOS Bridge Structure:
ios/SuperwallExpoModule.swift: Main Expo moduleios/Bridges/: Bridge classes for purchase controller and delegateios/Json/: JSON serialization extensions for native types
Android Bridge Structure:
android/src/main/java/expo/modules/superwallexpo/SuperwallExpoModule.kt: Main moduleandroid/src/main/java/expo/modules/superwallexpo/bridges/: Bridge classesandroid/src/main/java/expo/modules/superwallexpo/json/: JSON serialization extensions
Hooks-Based SDK (src/):
SuperwallProvider.tsx: React context provider for SDK initializationuseSuperwall.ts: Core store and SDK access hookuseUser.ts: User management and subscription statususePlacement.ts: Paywall registration and presentationuseSuperwallEvents.ts: Low-level event subscription
Compat SDK (src/compat/):
index.ts: Legacy Superwall class APIlib/: Type definitions and classes matching React Native SDK
Type System:
SuperwallExpoModule.types.ts: Comprehensive TypeScript definitions- All types extensively documented with JSDoc
- Bridge serialization ensures type safety across platforms
Uses Zustand for lightweight, type-safe state management:
- Centralized store in
useSuperwall.ts - Event-driven updates from native modules
- Shallow equality checking for performance
Critical pattern for extending native types:
When adding properties to native types:
- Update Swift JSON extension in
ios/Json/[Type]+Json.swift - Update Kotlin JSON extension in
android/src/main/java/expo/modules/superwallexpo/json/[Type].kt - Update TypeScript interface in
SuperwallExpoModule.types.ts - Update compat class in
src/compat/lib/[Type].tsif applicable
Example Pattern:
// iOS: TransactionProduct+Json.swift
extension TransactionProduct {
func toJson() -> [String: Any] {
return [
"id": id,
"price": price.toJson(),
// ... other properties
]
}
}// Android: TransactionProduct.kt
fun TransactionProduct.toJson(): Map<String, Any> {
return mapOf(
"id" to id,
"price" to price.toJson(),
// ... other properties
)
}Comprehensive event bridge between native SDKs and TypeScript:
- Native events → TypeScript via
SuperwallExpoModule.addListener - Type-safe event payloads defined in
SuperwallExpoModule.types.ts - Automatic cleanup on component unmount
The project supports both modern hooks and legacy class-based APIs:
- Hooks SDK:
import { usePlacement } from "expo-superwall" - Compat SDK:
import Superwall from "expo-superwall/compat"
src/SuperwallExpoModule.types.ts: Single source of truth for all TypeScript typessrc/useSuperwall.ts: Core store and SDK operationssrc/compat/index.ts: Legacy API implementationios/SuperwallExpoModule.swift&android/.../SuperwallExpoModule.kt: Native module entry points
iOS: SuperwallKit (CocoaPods) Android: Superwall SDK (Gradle)
Both are automatically managed through the respective native package managers.
The SDK relies heavily on integration testing through the example app rather than unit tests, due to the native bridge dependencies and paywall presentation logic.