All skills

Code generator skills that produce production-ready Swift code for common app components. Use when user wants to add logging, analytics, onboarding, review prompts, networking, authentication, paywalls, settings, persistence, error monitoring, CI/CD pipelines, localization, push notifications, deep linking, testing, accessibility, widgets, feature flags, app icons, image caching, pagination, HTTP caching, share cards, social export, subscription lifecycle, referral systems, watermarks, streak tracking, milestone celebrations, what's new screens, lapsed user re-engagement, usage insights, variable rewards, consent flows, account deletion, permission priming, force updates, state restoration, debug menus, offline queues, feedback forms, announcement banners, quick win sessions, Spotlight indexing, App Clips, screenshot automation, background processing, app extensions, data export, or SwiftUI preview sample data and variant matrices.

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/generators

This session only. Nothing lands on disk.

promoted-iaptemplates.md

≈2.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Promoted IAP Templates

Production-ready Swift code for handling promoted In-App Purchases.

PromotedPurchaseHandler.swift

import StoreKit
import SwiftUI

/// Handles purchases initiated from the App Store product page
@Observable
@MainActor
final class PromotedPurchaseHandler {

    static let shared = PromotedPurchaseHandler()

    private(set) var pendingPurchaseIntent: PurchaseIntent?
    private(set) var isProcessing = false

    /// The flow to show when a promoted purchase arrives
    enum PurchaseFlow: Identifiable {
        case directPurchase(Product)
        case showPaywall(Product)
        case showOnboarding(Product)

        var id: String {
            switch self {
            case .directPurchase(let p): "direct-\(p.id)"
            case .showPaywall(let p): "paywall-\(p.id)"
            case .showOnboarding(let p): "onboarding-\(p.id)"
            }
        }
    }

    private(set) var activePurchaseFlow: PurchaseFlow?

    // MARK: - Handle Purchase Intent

    /// Call this from your app's root view task to handle App Store purchases
    func handle(_ intent: PurchaseIntent) async {
        pendingPurchaseIntent = intent
        isProcessing = true

        let product = intent.product

        // Determine the right flow based on user state
        let flow = await determinePurchaseFlow(for: product)
        activePurchaseFlow = flow

        isProcessing = false
    }

    /// Complete the pending promoted purchase
    func completePurchase() async throws -> Transaction? {
        guard let intent = pendingPurchaseIntent else { return nil }

        let result = try await intent.product.purchase()

        switch result {
        case .success(let verification):
            guard case .verified(let transaction) = verification else {
                throw PromotedPurchaseError.verificationFailed
            }
            await transaction.finish()
            cleanup()
            return transaction

        case .userCancelled:
            cleanup()
            return nil

        case .pending:
            cleanup()
            return nil

        @unknown default:
            cleanup()
            return nil
        }
    }

    /// Cancel the pending promoted purchase
    func cancelPurchase() {
        cleanup()
    }

    // MARK: - Private

    private func determinePurchaseFlow(for product: Product) async -> PurchaseFlow {
        // Check if user has completed onboarding
        let hasCompletedOnboarding = UserDefaults.standard.bool(
            forKey: "hasCompletedOnboarding"
        )

        if !hasCompletedOnboarding {
            // New user from App Store — show onboarding first
            return .showOnboarding(product)
        }

        // Existing user — check if they should see the paywall
        // (e.g., to show other subscription options)
        if product.type == .autoRenewable {
            return .showPaywall(product)
        }

        // Direct purchase for non-subscription IAPs
        return .directPurchase(product)
    }

    private func cleanup() {
        pendingPurchaseIntent = nil
        activePurchaseFlow = nil
        isProcessing = false
    }
}

enum PromotedPurchaseError: LocalizedError {
    case verificationFailed
    case noPendingPurchase

    var errorDescription: String? {
        switch self {
        case .verificationFailed: "Purchase verification failed"
        case .noPendingPurchase: "No pending purchase to complete"
        }
    }
}

PromotedProductConfiguration.swift

import StoreKit

/// Configuration for promoted In-App Purchases
struct PromotedProductConfiguration {

    /// Products to promote on the App Store product page
    /// Listed in display priority order (first = most prominent)
    static let promotedProducts: [PromotedProduct] = [
        PromotedProduct(
            id: "com.yourapp.pro",
            displayName: "Pro Upgrade",
            promotionalImageName: "promo_pro_upgrade",
            promotionPriority: .high
        ),
        // Add more promoted products as needed
    ]

    /// All promoted product IDs
    static var productIDs: Set<String> {
        Set(promotedProducts.map(\.id))
    }
}

struct PromotedProduct: Identifiable {
    let id: String
    let displayName: String
    let promotionalImageName: String
    let promotionPriority: PromotionPriority

    enum PromotionPriority {
        case high   // First in list, most visible
        case medium // Middle of list
        case low    // End of list
    }
}

// MARK: - Promotional Image Guidelines

/*
 App Store Connect Promotional Image Requirements:

 SIZE: 1024 x 1024 pixels
 FORMAT: PNG or JPEG
 TRANSPARENCY: Not allowed (no alpha channel)
 CORNERS: Square (App Store rounds them automatically)

 CONTENT BEST PRACTICES:
 - Show the key benefit or feature being purchased
 - Use your app's color scheme and visual identity
 - Keep text minimal (product name appears separately)
 - Make it visually distinct from your app icon
 - Test at small sizes (appears as thumbnail in search)

 EXAMPLES BY IAP TYPE:
 - Subscription: Show premium features collage
 - Feature Unlock: Show the specific feature in action
 - Content Pack: Show sample content thumbnails
 - Credits/Tokens: Show the currency with quantity
*/

PromotedPurchaseFlowView.swift

import SwiftUI
import StoreKit

/// Root view modifier that handles promoted purchase flows
struct PromotedPurchaseFlowModifier: ViewModifier {
    @State private var handler = PromotedPurchaseHandler.shared

    func body(content: Content) -> some View {
        content
            .task {
                for await intent in PurchaseIntent.intents {
                    await handler.handle(intent)
                }
            }
            .sheet(item: $handler.activePurchaseFlow) { flow in
                PromotedPurchaseFlowView(flow: flow, handler: handler)
            }
    }
}

extension View {
    /// Add promoted purchase handling to this view
    func handlePromotedPurchases() -> some View {
        modifier(PromotedPurchaseFlowModifier())
    }
}

/// View that presents the appropriate flow for a promoted purchase
struct PromotedPurchaseFlowView: View {
    let flow: PromotedPurchaseHandler.PurchaseFlow
    let handler: PromotedPurchaseHandler

    @Environment(\.dismiss) private var dismiss
    @State private var isPurchasing = false
    @State private var purchaseError: String?

    var body: some View {
        NavigationStack {
            Group {
                switch flow {
                case .directPurchase(let product):
                    directPurchaseView(product: product)
                case .showPaywall(let product):
                    paywallView(product: product)
                case .showOnboarding(let product):
                    onboardingView(product: product)
                }
            }
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") {
                        handler.cancelPurchase()
                        dismiss()
                    }
                }
            }
        }
    }

    // MARK: - Direct Purchase

    @ViewBuilder
    private func directPurchaseView(product: Product) -> some View {
        VStack(spacing: 24) {
            Image(systemName: "star.circle.fill")
                .font(.system(size: 64))
                .foregroundStyle(.accent)

            Text(product.displayName)
                .font(.title.weight(.bold))

            Text(product.description)
                .font(.body)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)

            Text(product.displayPrice)
                .font(.title2.weight(.semibold))

            purchaseButton(product: product)

            if let error = purchaseError {
                Text(error)
                    .font(.caption)
                    .foregroundStyle(.red)
            }
        }
        .padding(32)
    }

    // MARK: - Paywall

    @ViewBuilder
    private func paywallView(product: Product) -> some View {
        // Use SubscriptionStoreView for subscription products
        if product.type == .autoRenewable,
           let groupID = product.subscription?.subscriptionGroupID {
            SubscriptionStoreView(groupID: groupID)
        } else {
            directPurchaseView(product: product)
        }
    }

    // MARK: - Onboarding

    @ViewBuilder
    private func onboardingView(product: Product) -> some View {
        VStack(spacing: 24) {
            Text("Welcome!")
                .font(.largeTitle.weight(.bold))

            Text("Thanks for checking out \(product.displayName). Here's what you'll get:")
                .font(.body)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)

            // Feature list - customize for your app
            VStack(alignment: .leading, spacing: 16) {
                FeatureBullet(icon: "checkmark.circle.fill", text: "Feature 1")
                FeatureBullet(icon: "checkmark.circle.fill", text: "Feature 2")
                FeatureBullet(icon: "checkmark.circle.fill", text: "Feature 3")
            }
            .padding()

            Spacer()

            purchaseButton(product: product)

            Button("Try Free First") {
                handler.cancelPurchase()
                dismiss()
            }
            .foregroundStyle(.secondary)
        }
        .padding(32)
    }

    // MARK: - Shared Purchase Button

    @ViewBuilder
    private func purchaseButton(product: Product) -> some View {
        Button {
            isPurchasing = true
            Task {
                do {
                    _ = try await handler.completePurchase()
                    dismiss()
                } catch {
                    purchaseError = error.localizedDescription
                }
                isPurchasing = false
            }
        } label: {
            if isPurchasing {
                ProgressView()
                    .frame(maxWidth: .infinity)
            } else {
                Text("Buy for \(product.displayPrice)")
                    .frame(maxWidth: .infinity)
            }
        }
        .buttonStyle(.borderedProminent)
        .controlSize(.large)
        .disabled(isPurchasing)
    }
}

private struct FeatureBullet: View {
    let icon: String
    let text: String

    var body: some View {
        HStack(spacing: 12) {
            Image(systemName: icon)
                .foregroundStyle(.green)
            Text(text)
        }
    }
}

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The 'generators' skill provides a robust set of templates and workflows for generating Swift code for iOS and macOS applications. Security analysis identified a surface for indirect prompt injection because the skill reads local project files to adapt its generation logic. It also utilizes dynamic execution by generating and running local Swift scripts to create application icons and uses shell commands to process images and audit project code. All external references are to well-known, established services.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: MEDIUM · 1 issue

  • Runlayer7mo

    59/179 files flagged

  • ZeroLeaks5mo

    Scan incomplete

Signed by skilld at 30e898f. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 2 months ago
What it can do
Reads files Edits files Runs commands
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 7 allowed tools
ReadWriteEditGlobGrepBashAskUserQuestion

README badge

README badge for rshankras/claude-code-apple-skills/generators