| name | ios-paywall-creator |
| description | Create production-grade iOS paywalls with StoreKit 2 integration for subscriptions and in-app purchases.
Use this skill whenever the user mentions paywalls, monetization, subscriptions, StoreKit, IAP, in-app purchases,
RevenueCat alternatives, or wants to add payment features to their iOS app. This skill guides developers through
the complete process from App Store Connect setup to beautiful paywall UI implementation, even if they don't
explicitly ask for a "paywall" - trigger for any subscription or IAP-related requests.
|
iOS Paywall Creator
This skill helps iOS developers create production-ready paywalls with native StoreKit 2 implementation. It provides a guided workflow from App Store Connect configuration to polished UI implementation.
Workflow Overview
The skill follows a structured process:
- Discovery - Understand the app's monetization needs
- Product Planning - Define subscription tiers or IAP products
- App Store Connect Setup - Guide through subscription/IAP creation
- Design Phase - Gather inspiration and define the paywall aesthetic
- Implementation - Generate production-ready Swift code
Using Interactive Questions
Throughout this workflow, you'll use the AskUserQuestion tool to gather user preferences. This provides a native MCQ (multiple-choice question) interface that's much better than text-based questions.
When you see instructions like this:
question: "Which subscription durations do you want to offer?"
header: "Durations"
multiSelect: false
options:
- label: "All Three: Weekly, Monthly & Yearly (Recommended)"
description: "Maximum flexibility..."
You should call the AskUserQuestion tool like this:
AskUserQuestion with:
- questions: [
{
question: "Which subscription durations do you want to offer?",
header: "Durations",
multiSelect: false,
options: [
{
label: "All Three: Weekly, Monthly & Yearly (Recommended)",
description: "Maximum flexibility - users choose based on commitment level..."
},
...
]
}
]
This creates a clean, interactive interface where users can click their choice instead of typing responses. Always use this pattern when you see question blocks in the instructions below.
Step 1: Discovery & Product Planning
Start by understanding what the user needs to monetize.
Gather Core Information:
Use the AskUserQuestion tool to collect essential information:
-
Product Type - Use AskUserQuestion:
question: "What type of in-app products do you want to offer?"
header: "Product Type"
multiSelect: false
options:
- label: "Auto-renewing Subscriptions (Recommended)"
description: "Recurring revenue model - users get ongoing access and are charged weekly/monthly/yearly. Best for content apps, productivity tools, and services. Highest lifetime value."
- label: "Consumable IAP"
description: "One-time purchases that get used up - like credits, tokens, or coins. Users can buy repeatedly. Good for games or apps with consumable resources."
- label: "Non-consumable IAP"
description: "One-time purchases that unlock features forever - like 'Remove Ads' or 'Unlock Premium'. Users buy once and own forever."
-
Paywall Location - Use AskUserQuestion:
question: "Where should the paywall appear in your app?"
header: "Placement"
multiSelect: true
options:
- label: "First Launch (Recommended)"
description: "Show paywall on first app open as a soft introduction. Good for establishing value early without being pushy."
- label: "Hard Paywall / Feature Gate"
description: "Block access to specific features until user subscribes. Most effective for converting users who see clear value."
- label: "Settings / Upgrade Section"
description: "User-initiated from a settings menu or upgrade button. Low pressure, but requires users to discover it."
- label: "After Trial Period"
description: "Show paywall after users have used the app for a few days/launches. Captures users who've experienced value."
-
Ask as plain text: "What features are locked behind the paywall?"
Understanding this helps contextualize the value proposition in the UI.
Step 2: Subscription/IAP Planning
Based on their product type choice, guide them through planning:
For Auto-Renewing Subscriptions:
Subscription Durations - Use AskUserQuestion:
question: "Which subscription durations do you want to offer?"
header: "Durations"
multiSelect: false
options:
- label: "All Three: Weekly, Monthly & Yearly (Recommended)"
description: "Maximum flexibility - users choose based on commitment level. Weekly for trial, Monthly most popular, Yearly for highest LTV. Covers all user preferences."
- label: "Monthly & Yearly Only"
description: "Most common setup - balances simplicity with choice. Monthly for casual users, Yearly for committed users. Skip weekly to reduce options."
- label: "Monthly Only"
description: "Simplest option - one price point to manage. Good for starting out, but limits revenue optimization opportunities."
- label: "Custom Combination"
description: "Choose your own mix - like Weekly + Yearly or just Yearly. Tell me which durations you want."
For each tier they've selected, they'll need to decide:
- Display Name (e.g., "Premium Weekly", "Pro Monthly")
- Price (you'll guide them through App Store Connect pricing)
- Product ID (e.g.,
com.yourapp.premium.weekly)
- Duration (7 days, 1 month, 1 year)
Free Trials & Introductory Offers - Use AskUserQuestion:
question: "Do you want to offer a free trial or introductory offer?"
header: "Trial Offer"
multiSelect: false
options:
- label: "Free Trial (Recommended)"
description: "Users get X days free before first charge (e.g., '7-day free trial', '3-day free trial'). Best for conversion - lets users experience value risk-free. Industry standard."
- label: "Introductory Price"
description: "Discounted price for first billing period (e.g., '$0.99 for first month, then $9.99'). Good alternative if you want some upfront revenue."
- label: "Pay Up Front Discount"
description: "Reduced price for multiple periods paid upfront (e.g., '3 months for $19.99, then $9.99/month'). Less common but good for cash flow."
- label: "No Trial or Offer"
description: "Standard pricing from day one. Use if your value is immediately clear or you have other onboarding strategies."
If they select a trial option, follow up by asking:
- For Free Trial: "How long should the free trial be?" (Common: 3 days, 7 days, 14 days, 1 month)
- For Introductory Price: "What should the intro price be and for how long?" (e.g., "$0.99 for first month")
- For Pay Up Front: "What's the discounted price and duration?" (e.g., "$19.99 for 3 months")
Important: Trials apply to new subscribers only. Users who've already had a trial won't see the offer again.
Multiple Subscription Tiers - Use AskUserQuestion:
question: "Do you need multiple subscription tiers with different feature sets?"
header: "Tier Structure"
multiSelect: false
options:
- label: "Single Tier"
description: "One 'Premium' or 'Pro' subscription that unlocks everything. Simplest to manage and explain. Recommended for most apps."
- label: "Multiple Tiers (Basic/Premium/Ultimate)"
description: "Different tiers with different features (e.g., Basic gets X, Premium gets X+Y, Ultimate gets everything). More complex but can capture more user segments."
If they choose multiple tiers, ask them to describe what features each tier includes. Each tier needs a separate subscription group in App Store Connect.
For Consumable IAP:
Ask about each consumable product:
- What does it provide? (e.g., "100 AI credits", "50 tokens")
- Product ID (e.g.,
com.yourapp.tokens.100)
- Display Name
- Price tier
For Non-Consumable IAP:
Similar to consumables, but emphasize this is a one-time purchase that persists forever.
Step 3: App Store Connect Configuration & ID Collection
This is a critical step where many developers get stuck. Provide clear, step-by-step guidance, then collect the actual IDs to use in code generation.
For Subscriptions:
-
Navigate to App Store Connect:
-
Create Subscription Group:
- Click "+" to create a new subscription group
- Give it a reference name (e.g., "Premium Access")
- Important: Save the Subscription Group ID - they'll need this in code
-
Add Subscriptions to Group:
For each tier (weekly/monthly/yearly):
a. Click "+" to add a subscription to the group
b. Reference Name: Internal name (e.g., "Premium Weekly")
c. Product ID: Reverse domain format
- Example:
com.yourcompany.appname.premium.weekly
- Must be unique and cannot be changed later
- Use lowercase, no spaces
d. Subscription Duration:
- Weekly: 7 days
- Monthly: 1 month
- Yearly: 1 year
e. Pricing:
- Click "Add Pricing"
- Select "Automatic Pricing" (recommended) or set custom per territory
- Choose a price tier (e.g., $4.99/week, $9.99/month, $49.99/year)
f. Localization:
- Add display name and description for each language
- This is what users see in the App Store
g. Subscription Prices (Introductory Offers):
If the user wants a free trial or intro offer:
- Click "Add Introductory Offer" in the Subscription Prices section
- Choose offer type:
- Free Trial: Select duration (3 days, 7 days, 2 weeks, 1 month, etc.)
- Pay As You Go: Discounted price per billing period
- Pay Up Front: One-time discounted price for multiple periods
- Select duration (how long the offer lasts)
- Click "Create" and it will apply to all territories
- Important: Each subscription can only have ONE introductory offer
- Users are eligible once per subscription group (won't see offer again after canceling)
h. App Store Information:
- Upload subscription benefits screenshots if needed
- Add promotional text
- If using trials, mention it: "Start your 7-day free trial"
-
Set Up Subscription Group Info:
- Return to the subscription group level
- Add localized display name for the group
- This appears in Settings when users manage subscriptions
-
Get Your Subscription Group ID:
- In the subscription group overview, find the "Group ID"
- It's usually a numeric value like "21995608"
- Copy this - you'll use it in
StoreKitManager
For In-App Purchases (Consumables/Non-Consumables):
-
Navigate to App Store Connect:
- Go to your app → "Features" → "In-App Purchases"
-
Create IAP:
- Click "+" to create new in-app purchase
- Select type (Consumable or Non-Consumable)
-
Configure:
- Reference Name: Internal identifier
- Product ID: e.g.,
com.yourapp.tokens.100
- Pricing: Same process as subscriptions
- Localization: Display name and description
-
Important: For consumables that need backend verification (like credits), note that you'll need to track these server-side.
StoreKit Configuration File (Optional but Recommended):
For testing in Xcode:
- File → New → File → "StoreKit Configuration File"
- Add your products manually for local testing
- This lets you test purchases without App Store Connect
Collect Product IDs (Critical for Code Generation)
After they've created their products in App Store Connect, ask them to provide the actual IDs so you can generate code that works immediately without placeholders.
For Subscriptions, ask:
"Now that you've created your subscriptions in App Store Connect, please provide:
- Subscription Group ID (found in the subscription group overview - usually a numeric value like '21995608')
- Product IDs for each subscription you created (e.g., 'com.yourapp.premium.weekly', 'com.yourapp.premium.monthly', 'com.yourapp.premium.yearly')
I'll use these exact IDs in the generated code so it's ready to use immediately."
For IAP products, ask:
"Please provide the Product IDs for each in-app purchase you created (e.g., 'com.yourapp.tokens.100', 'com.yourapp.unlock.premium')"
Store these values - you'll insert them directly into the generated code, replacing all placeholders. The user should not have to manually edit product IDs in the generated code.
Step 4: Design & Inspiration Phase
Now that products are configured, design the paywall UI.
Gather Inspiration:
Use AskUserQuestion to determine the design approach:
question: "How would you like to define the paywall design?"
header: "Design Input"
multiSelect: false
options:
- label: "I'll Provide a Screenshot (Recommended)"
description: "Upload an image of a paywall you like from another app. I'll analyze the colors, layout, typography, and recreate that style for your app."
- label: "Describe the Style I Want"
description: "Tell me your vision in words (e.g., 'modern and minimal', 'bold with gradients', 'warm and friendly'). I'll design based on your description."
- label: "Show Me Design Options"
description: "I'll generate 2-3 distinct theme options (Modern Minimalist, Warm & Friendly, Bold & Premium) and you can choose your favorite."
- label: "Copy a Specific App's Style"
description: "Name an app whose paywall you like (e.g., 'Duolingo', 'Notion', 'Calm') and I'll research and recreate that aesthetic."
If they provide an image:
-
Analyze the image carefully:
- Color scheme
- Layout structure (comparison table, card-based, minimal, feature-rich)
- Typography style
- Use of gradients, shadows, borders
- Button style
- Badge/highlight elements ("BEST VALUE", "SAVE 60%")
-
Ask clarifying questions:
- "I see this uses a bold orange accent - should we keep that or adjust?"
- "The layout shows a comparison table - do you want exactly that structure?"
- "Should we include badges like 'BEST VALUE' on certain tiers?"
If they provide a description:
Extract the aesthetic direction and confirm:
- Tone (minimal, bold, playful, professional, luxurious)
- Colors mentioned
- Any specific UI elements
If they want options:
Generate 2-3 distinct themes and present them to the user. Then use AskUserQuestion to let them choose:
Example themes to generate:
Option 1: Modern Minimalist
- Colors: Deep navy (#1a1f36) with electric blue accent (#00d4ff)
- Clean sans-serif fonts
- Generous white space
- Subtle shadows
- Card-based layout
Option 2: Warm & Friendly
- Colors: Soft peach (#ffe5d9) background with coral accent (#ff6b6b)
- Rounded corners everywhere
- Playful illustrations or icons
- Gentle gradients
Option 3: Bold & Premium
- Colors: Rich purple (#6366f1) to indigo gradient
- Gold accents (#fbbf24)
- Dramatic shadows
- Strong typography
- Luxury feel
After presenting the theme descriptions with color swatches, use AskUserQuestion:
question: "Which design theme do you prefer for your paywall?"
header: "Theme Choice"
multiSelect: false
options:
- label: "Modern Minimalist"
description: "Deep navy with electric blue accent. Clean, professional, generous spacing. Card-based layout with subtle shadows."
- label: "Warm & Friendly"
description: "Soft peach background with coral accent. Rounded corners, playful feel, gentle gradients. Approachable and inviting."
- label: "Bold & Premium"
description: "Purple-indigo gradient with gold accents. Dramatic shadows, strong typography. Conveys luxury and exclusivity."
Confirm Before Coding:
After settling on a direction, show a brief description of what you'll build:
I'll create a paywall with:
- [Color scheme description]
- [Layout type: comparison table / card grid / minimal list]
- Subscription options: [Weekly $X, Monthly $Y, Yearly $Z]
- Features highlight section showing: [feature 1, feature 2, feature 3]
- [Any special elements like badges, animations]
Wait for explicit approval before generating code. Ask: "Does this sound right? Any changes to the design direction or features to highlight?"
Step 5: Code Generation
Now generate production-ready Swift code using the reference templates.
Pre-Generation Checklist
Before generating code, verify you have collected:
For Subscriptions:
- ✅ Subscription Group ID (numeric, e.g., "21995608")
- ✅ Product ID for each tier (e.g., "com.reelmark.premium.weekly")
- ✅ Which tiers they're using (weekly/monthly/yearly)
For IAP:
- ✅ Product ID for each IAP (e.g., "com.yourapp.tokens.100")
- ✅ Type (consumable or non-consumable)
For UI:
- ✅ Design direction confirmed
- ✅ Color scheme defined
- ✅ Features to highlight
- ✅ Terms of Service URL
- ✅ Privacy Policy URL
If any of these are missing, ask for them now before generating code.
Core Components to Generate:
-
StoreKitManager.swift - Based on references/storekit-manager-template.md
- Transaction observer for real-time updates
- Product loading and purchase flow
- Subscription status checking
- Error handling
-
PaywallView.swift - Custom UI based on user's design inspiration
- SwiftUI view with their chosen aesthetic
- Product selection interface
- Feature comparison (if applicable)
- Terms of service and privacy policy links
-
Integration Instructions - How to add the paywall to their app
- Import statements
- App initialization code
- Where to present the paywall
Code Generation Guidelines:
Use Reference Code Patterns:
Read references/storekit-manager-template.md and references/paywall-view-template.md for proven patterns. Don't reinvent the wheel - these templates have:
- Proper transaction verification
- Real-time subscription updates
- Correct async/await patterns
- Error handling
Customize Based on User's Setup:
CRITICAL: Use the actual IDs they provided - do NOT use placeholders like "YOUR_GROUP_ID" or "com.yourapp.premium.weekly"
Insert their real values:
- Subscription Group ID: Use the exact numeric ID they gave you (e.g., "21995608")
- Product IDs: Use their exact product IDs for each tier (e.g., "com.reelmark.premium.weekly")
- Variable names: Keep descriptive (e.g.,
weeklySubscriptionID, monthlySubscriptionID)
- Adapt
isProUser logic based on their tier structure
- For IAP: include the consumable/non-consumable product IDs in the
Product.products(for:) array
The generated code should work immediately when they copy it into their project - no manual ID replacement needed.
UI Customization:
Follow the design inspiration closely:
- Apply their color scheme using SwiftUI's
.foregroundStyle() and Color()
- Match layout structure (cards, table, list)
- Include any special elements (badges, gradients, animations)
- Implement their typography preferences
If they configured free trials or intro offers:
- Display trial information prominently using StoreKit's built-in properties
- Use
product.subscription?.introductoryOffer to check for offers
- Show trial duration: "7-day free trial", "Try free for 7 days"
- Include "then $9.99/month" to show price after trial
- Use the Product extension methods in the reference for
introOfferDescription
- Consider highlighting trial offers with badges or special styling
- Make it clear in the button text if it's free trial or not.
Required Legal Elements:
Always include:
- Link to Terms of Service
- Link to Privacy Policy
- Text: "Subscriptions automatically renew unless cancelled"
- For Apple's standard EULA:
https://www.apple.com/legal/internet-services/itunes/dev/stdeula/
- "Restore Purchases" button
Ask the user for their Terms and Privacy Policy URLs, or help them understand they need these.
Best Practices to Include:
- Use
@Observable macro for StoreKitManager (iOS 17+) or ObservableObject for older versions
- Load products on initialization
- Auto-select a recommended plan (usually monthly)
- Show loading states
- Handle errors gracefully with user-friendly messages
- Include "Manage Subscription" button for existing subscribers
- Add intro offer support if they plan to use it
Output Format:
Present the code as:
- A complete markdown document with separate code blocks for each file
- Each file clearly labeled with
// MARK: - Filename
- Include inline comments explaining key sections
- Provide a "Quick Start" section showing how to integrate
Example structure:
# Your iOS Paywall Implementation
✅ **All product IDs have been configured with your actual values from App Store Connect**
## 1. StoreKitManager.swift
Create this file in your project. All product IDs are already configured:
[Full code block with ACTUAL IDs]
## 2. PaywallView.swift
Create this file in your project:
[Full code block with user's design]
## 3. Integration
In your App struct or main view:
[Integration code]
## 4. Required Assets
- Add a paywall header image (if applicable): `PaywallImage` in Assets.xcassets
- Your product IDs are already in the code - no manual configuration needed!
## 5. Testing
[Testing instructions]
Important: At the top of the generated code, include a summary showing which IDs were used, so the user can verify they're correct at a glance.
Step 6: Integration Guidance
After generating code, provide clear instructions on:
Where to Show the Paywall:
Based on their earlier answers about where paywalls should appear:
First Launch:
.onAppear {
if !UserDefaults.standard.bool(forKey: "hasSeenPaywall") {
showPaywall = true
UserDefaults.standard.set(true, forKey: "hasSeenPaywall")
}
}
Hard Paywall (Feature Gate):
if !storeManager.isProUser {
PaywallView()
} else {
PremiumFeatureView()
}
Settings/Upgrade Button:
Button("Upgrade to Premium") {
showPaywall = true
}
.sheet(isPresented: $showPaywall) {
PaywallView()
}
Initialize StoreKit:
In the App struct:
@main
struct YourApp: App {
init() {
StoreKitManager.shared.configure()
}
}
Testing Checklist:
Provide a testing checklist:
Design Best Practices
When creating the UI, follow these principles to avoid generic "AI slop" aesthetics:
Typography
- Choose distinctive fonts that match the app's personality
- Avoid overused options (SF Pro is fine but consider custom fonts)
- Create hierarchy with size and weight
- Consider system font with design variation (
.rounded, .serif)
Color & Theme
- Commit to a cohesive palette
- Use the user's brand colors if they mention them
- Dominant color with sharp accents > evenly distributed pastels
- Support both light and dark mode (use
.primary, .secondary for adaptive colors)
Layout
- Don't be afraid of asymmetry
- Use generous spacing or controlled density (not in between)
- Consider scroll effects or animations for delight
- Make the best value option stand out visually
Visual Details
- Add depth with shadows (
.shadow())
- Use gradients thoughtfully (
.fill(LinearGradient(...)))
- Rounded corners for friendliness (
.cornerRadius())
- Highlight badges for "SAVE 60%" or "BEST VALUE"
- Consider subtle animations on appear
What to Avoid
- Generic purple gradients on white backgrounds
- Cookie-cutter comparison tables (add personality)
- Cluttered information (prioritize clarity)
- Tiny legal text (make it readable)
Reference Code
All reference implementations are available in:
references/storekit-manager-template.md - Complete StoreKit 2 manager
references/paywall-view-template.md - Customizable paywall UI examples
references/integration-patterns.md - Common integration scenarios
Read these before generating code to ensure you're following proven patterns.
Common Issues & Solutions
"Products not loading"
- Check product IDs match exactly (case-sensitive)
- Ensure subscription group exists in App Store Connect
- Verify app's Bundle ID matches
- Check "Cleared for Sale" is enabled
- Try
try await AppStore.sync() to refresh
"Purchase completes but status doesn't update"
- Ensure
checkPurchasedProducts() is called after purchase
- Verify transaction observer is initialized
- Check
Transaction.currentEntitlements logic
"UI looks wrong on smaller devices"
- Use
GeometryReader for adaptive sizing
- Test on iPhone SE (smallest screen)
- Use
.minimumScaleFactor() for text that must fit
Final Deliverable
The complete implementation package should include:
- ✅
StoreKitManager.swift - Fully configured with user's product IDs
- ✅
PaywallView.swift - Custom UI matching their design inspiration
- ✅ Integration instructions for their specific use case
- ✅ Testing checklist
- ✅ Links to required documentation
Remind the user:
- They need to submit their app with working IAP to App Store Review
- Test thoroughly in sandbox environment before release
- Consider offering a free trial (configured in App Store Connect)
- Monitor subscription metrics in App Store Connect