storekit
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.
Works with
---
name: storekit
description: 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.
license: MIT
---
# StoreKit
StoreKit 2 patterns for implementing in-app purchases with async/await APIs, automatic verification, and SwiftUI integration.
## Reference Loading Guide
**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](references/getting-started.md)** | Setting up `.storekit` configuration file, testing-first workflow |
| **[Products](references/products.md)** | Loading products, product types, purchasing with `Product.purchase()` |
| **[Subscriptions](references/subscriptions.md)** | Auto-renewable subscriptions, subscription groups, offers, renewal tracking |
| **[Transactions](references/transactions.md)** | Transaction listener, verification, finishing transactions, restore purchases |
| **[StoreKit Views](references/storekit-views.md)** | ProductView, SubscriptionStoreView, SubscriptionOfferView in SwiftUI |
## Core Workflow
1. Create `.storekit` configuration file first (before any code)
2. Test purchases locally in Xcode simulator
3. Implement centralized `StoreManager` with `@MainActor`
4. Set up `Transaction.updates` listener at app launch
5. Display products with `ProductView` or custom UI
6. Always call `transaction.finish()` after granting entitlements
## Essential Architecture
```swift
@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() }
}
}
```
## Common Mistakes
1. **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()`.
2. **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.
3. **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.
4. **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).
5. **Ignoring verification failures** — App Store verification fails silently sometimes. Not checking verification status means accepting unverified transactions (security risk). Always verify before granting entitlements.More Testing skills
tdd
mattpocock/skills
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
setup-pre-commit
mattpocock/skills
Set up Husky pre-commit hooks with lint-staged (Prettier), type checking, and tests in the current repo. Use when user wants to add pre-commit hooks, set up Husky, configure lint-staged, or add commit-time formatting/typechecking/testing.
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.

