swiftship/internal/skills/data/features/revenuecat/SKILL.md
RevenueCat SDK patterns for in-app purchases, subscriptions, and entitlements. Use when implementing monetization features with RevenueCat.
npx skillsauth add abdullah4ai/apple-dev-docs revenuecatInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Configure RevenueCat in your App's init() with StoreKit 2:
import RevenueCat
@main
struct MyApp: App {
init() {
#if DEBUG
Purchases.logLevel = .debug
#endif
Purchases.configure(
with: Configuration.Builder(withAPIKey: AppConfig.revenueCatAPIKey)
.with(storeKitVersion: .storeKit2)
.build()
)
}
}
The API key comes from AppConfig.revenueCatAPIKey — NEVER hardcode it inline.
let offerings = try await Purchases.shared.offerings()
if let current = offerings.current {
for package in current.availablePackages {
let product = package.storeProduct
let price = product.localizedPriceString // "$9.99" — dynamic from store
let name = product.localizedTitle // "Premium Monthly"
}
}
let result = try await Purchases.shared.purchase(package: package)
if !result.userCancelled {
let isPremium = result.customerInfo.entitlements[AppConfig.entitlementID]?.isActive == true
}
Handle errors:
.purchaseCancelledError — user tapped Cancel, do nothing.paymentPendingError — payment pending approval (Ask to Buy).storeProblemError — App Store issue, show retry.purchaseNotAllowedError — device restrictionsALWAYS use AppConfig.entitlementID — never hardcode the entitlement string:
let customerInfo = try await Purchases.shared.customerInfo()
let isPremium = customerInfo.entitlements[AppConfig.entitlementID]?.isActive == true
for try await customerInfo in Purchases.shared.customerInfoStream {
let isPremium = customerInfo.entitlements[AppConfig.entitlementID]?.isActive == true
}
let customerInfo = try await Purchases.shared.restorePurchases()
When using authentication (Supabase, Firebase, etc.), link the user ID:
let (customerInfo, _) = try await Purchases.shared.logIn(userId)
Call logIn after the user authenticates. Call logOut on sign-out:
let customerInfo = try await Purchases.shared.logOut()
AppConfig.revenueCatAPIKeyAppConfig.entitlementIDAppConfig.ProductID constantspackage.storeProduct.localizedPriceString — NEVER hardcode dollar amountsSee SDK Setup, Purchase Flow, and Entitlements for detailed patterns.
testing
Use for 3D games: racing, 3D sports, board games, marble maze, tower defense, bowling. SceneKit + SceneView architecture, 3D scene hierarchy, physics, game loop, primitives, materials, cameras, particles, audio.
documentation
Game UI patterns: SwiftUI HUD overlays on SpriteKit, menus (main/pause/game-over), virtual joystick/d-pad, score displays, health bars, tutorial onboarding.
tools
Download free game sprites/textures/3D models and generate procedural assets. Covers nw_download_asset tool, texture factories, sprite atlas organization, 3D model loading, and programmatic asset creation.
testing
Use for 2D games: arcade, puzzle, sports, ping pong, platformer, shooter, 2D racing. SpriteKit + SpriteView architecture, scene hierarchy, physics, game loop, audio, particles, game feel.