Flare is a modern, lightweight Swift framework that simplifies working with in-app purchases and subscriptions. Built on top of StoreKit and StoreKit 2, it provides a clean, unified API with async/await support and includes ready-to-use UI components for seamless integration across all Apple platforms.
- 🛍️ Complete Purchase Support - Consumable, non-consumable, and subscription purchases
- 🎁 Promotional Offers - Support for promotional and introductory offers
- ⚡ Modern Swift - Built with async/await for clean, readable code
- 🔄 StoreKit 1 & 2 - Unified API supporting both StoreKit versions
- 🎨 UI Components - Pre-built SwiftUI and UIKit views for product displays
- 📱 Cross-Platform - iOS, tvOS, watchOS, macOS, and visionOS compatible
- 🧪 Thoroughly Tested - Complete unit, integration, and snapshot test coverage
| Package | Supported Platforms | Xcode | Minimum Swift Version |
|---|---|---|---|
| Flare | iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 7.0+ / visionOS 1.0+ | 15.4+ | 5.10 |
| FlareUI | iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ | 15.4+ | 5.10 |
Add the following dependency to your Package.swift:
dependencies:[.package(url:"https://github.com/space-code/flare.git", from:"3.3.0")]Or via Xcode:
- File > Add Package Dependencies
- Enter package URL:
https://github.com/space-code/flare.git - Select version requirements
The package contains two libraries:
- Flare - Core in-app purchase functionality
- FlareUI - Ready-to-use UI components for SwiftUI and UIKit
import Flare
// Configure Flare
Flare.configure(with:.init(applicationUsername:"UUID"))
// Fetch products
letproducts=tryawaitFlare.shared.fetch(productIDs:["premium_monthly"])
// Purchase a product
lettransaction=tryawaitFlare.shared.purchase(product: products.first!)
// Finish the transaction
Flare.shared.finish(transaction: transaction, completion:nil)Retrieve product information from the App Store:
import Flare
// Fetch single product
letproductIDs=["com.app.premium"]letproducts=tryawaitFlare.shared.fetch(productIDs: productIDs)
// Fetch multiple products
letsubscriptionIDs=["com.app.monthly","com.app.yearly","com.app.lifetime"]letsubscriptions=tryawaitFlare.shared.fetch(productIDs: subscriptionIDs)
// Access product details
forproductin products {print("Product: \(product.localizedTitle)")print("Price: \(product.localizedPriceString)")print("Description: \(product.localizedDescription)")}Handle purchases with simple async/await syntax:
import Flare
func purchasePremium()asyncthrows{letproductID="com.app.premium"letproducts=tryawaitFlare.shared.fetch(productIDs:[productID])guardlet product = products.first else{throwIAPError.storeProductNotAvailable
}do{lettransaction=tryawaitFlare.shared.purchase(product: product)awaitunlockPremiumFeatures()Flare.shared.finish(transaction: transaction, completion:nil)}catch{guardlet error = error as?IAPErrorelse{return}switch error {case.paymentCancelled:print("❌ User cancelled the purchase")default:print("❌ Purchase failed: \(error)")}}}Work with subscription products and their states:
import Flare
func purchaseSubscription(product:StoreProduct)asyncthrows{do{lettransaction=tryawaitFlare.shared.purchase(product: product)Flare.shared.finish(transaction: transaction, completion:nil)}catch{guardlet error = error as?IAPErrorelse{return}
// Handle the error
}}Manage transaction lifecycle:
import Flare
// Finish a transaction after delivering content
func completeTransaction(_ transaction:StoreTransaction){Flare.shared.finish(transaction: transaction){print("✅ Transaction completed successfully")}}
// Restore previous purchases
func restorePurchases()asyncthrows{do{tryawaitFlare.shared.restore()print("✅ Purchases restored successfully")}catch{print("❌ Failed to restore purchases: \(error)")}}
// Listen for transaction updates
func observeTransactions(){Flare.shared.addTransactionObserver{ result inswitch result {caselet.success(transaction):handleTransaction(transaction)caselet.failure(error):print("Transaction error: \(error)")}}}Support promotional and introductory offers:
import Flare
func purchaseWithOffer(product:StoreProduct, offer:PromotionalOffer)asyncthrows{do{lettransaction=tryawaitFlare.shared.purchase(
product: product,
promotionalOffer: offer
)print("✅ Purchased with promotional offer!")Flare.shared.finish(transaction: transaction, completion:nil)}catch{guardlet error = error as?IAPErrorelse{return}
// Handle the error
}}FlareUI provides ready-to-use UI components for displaying products and handling purchases in both SwiftUI and UIKit.
Display products with built-in SwiftUI views:
import SwiftUI
import FlareUI
structStoreView:View{varbody:someView{NavigationView{SubscriptionsView(ids:["com.product.subscription"]).navigationTitle("Premium Features")}}}Integrate with UIKit applications:
import UIKit
import FlareUI
letsubscriptionsVC=SubscriptionsViewController(ids:[com.company.subscription_id])letnav=UINavigationController(rootViewController: subscriptionsVC)present(nav, animated:true)Comprehensive documentation is available:
- Flare Documentation - Core framework integration and APIs
- FlareUI Documentation - UI components, customization, and integration guides
We love contributions! Please read our Contributing Guide to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.
Bootstrap the development environment:
mise installThis project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
Nikita Vasilev
- Email: nv3212@gmail.com
- GitHub: @ns-vasilev
Flare is released under the MIT license. See LICENSE for details.
Made with ❤️ by space-code
