Use when implementing in-app purchases, StoreKit 2 subscriptions, consumables, non-consumables, or transaction handling. Covers testing-first workflow with .storekit configuration, StoreManager architecture, and transaction verification.
/plugin marketplace add johnrogers/claude-swift-engineering/plugin install swift-engineering@claude-swift-engineeringThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/getting-started.mdreferences/products.mdreferences/storekit-views.mdreferences/subscriptions.mdreferences/transactions.mdStoreKit 2 patterns for implementing in-app purchases with async/await APIs, automatic verification, and SwiftUI integration.
ALWAYS load reference files if there is even a small chance the content may be required. It's better to have the context than to miss a pattern or make a mistake.
| Reference | Load When |
|---|---|
| Getting Started | Setting up .storekit configuration file, testing-first workflow |
| Products | Loading products, product types, purchasing with Product.purchase() |
| Subscriptions | Auto-renewable subscriptions, subscription groups, offers, renewal tracking |
| Transactions | Transaction listener, verification, finishing transactions, restore purchases |
| StoreKit Views | ProductView, SubscriptionStoreView, SubscriptionOfferView in SwiftUI |
.storekit configuration file first (before any code)StoreManager with @MainActorTransaction.updates listener at app launchProductView or custom UItransaction.finish() after granting entitlements@MainActor
final class StoreManager: ObservableObject {
@Published private(set) var products: [Product] = []
@Published private(set) var purchasedProductIDs: Set<String> = []
private var transactionListener: Task<Void, Never>?
init() {
transactionListener = listenForTransactions()
Task { await loadProducts() }
}
}
Missing .finish() calls on transactions — Forgetting to call transaction.finish() after granting entitlements causes transactions to never complete. The user won't see their purchase reflected. Always call finish().
Unsafe StoreManager state — Shared StoreManager without @MainActor can have race conditions. Multiple async tasks can update @Published properties concurrently, corrupting state. Use @MainActor for thread safety.
No transaction listener at app launch — Not setting up Transaction.updates listener means app crashes or misses refunded/canceled purchases. Listen for transactions immediately in @main, not when user taps purchase button.
Hardcoded product IDs — Hardcoded IDs make testing and localization hard. Use configuration files or environment variables for product IDs. Same applies to prices (fetch from App Store, don't hardcode).
Ignoring verification failures — App Store verification fails silently sometimes. Not checking verification status means accepting unverified transactions (security risk). Always verify before granting entitlements.
This skill should be used when the user asks about libraries, frameworks, API references, or needs code examples. Activates for setup questions, code generation involving libraries, or mentions of specific frameworks like React, Vue, Next.js, Prisma, Supabase, etc.