Complete guide for deploying your iOS app to TestFlight and the App Store.
- Pre-Deployment Checklist
- Build Configuration
- Archive and Upload
- TestFlight Setup
- App Store Submission
- CI/CD with GitHub Actions
- Post-Submission
- Release Checklist
Before creating your first release, ensure everything is ready:
- All features tested thoroughly
- No critical bugs remaining
- Unit tests passing (if applicable)
- No TODO/FIXME comments in production code
- Debug logging disabled or removed
- No test data in production code
- Production API keys configured in
AppConfiguration.swift - Correct Supabase URL and keys (production, not debug)
- RevenueCat production API key set
- App Store ID configured for update checker
- All service integrations tested
- App icon created and added (all required sizes)
- Launch screen configured
- Screenshots prepared (all required device sizes)
- App preview videos (optional but recommended)
- Privacy Policy URL valid and accessible
- Terms of Service URL valid
- App complies with App Store Review Guidelines
- Third-party licenses documented
- Age rating determined
- App created in App Store Connect
- All metadata complete (name, subtitle, description, keywords)
- Support URL configured
- Marketing URL (if applicable)
- Demo account credentials prepared (if app requires login)
Release builds are optimized and remove debug features.
In Xcode:
- Click the scheme selector (next to Play/Stop buttons)
- Click Edit Scheme...
- Select Run in the left sidebar
- Build Configuration dropdown → Select Release
- Close
Version Number (CFBundleShortVersionString):
- Semantic versioning:
MAJOR.MINOR.PATCH - Example:
1.0.0for first release - Increment for each release:
- Major: Breaking changes (1.0.0 → 2.0.0)
- Minor: New features (1.0.0 → 1.1.0)
- Patch: Bug fixes (1.0.0 → 1.0.1)
Build Number (CFBundleVersion):
- Integer that increments with each upload
- Example:
1,2,3, etc. - Must be higher than previous build for the same version
Update in Xcode:
- Select project → iOSJumpstart target → General
- Identity section:
- Version:
1.0.0(or your version) - Build:
1(increment for each upload)
- Version:
Alternatively, edit Info.plist directly:
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>Update AppConfiguration.swift with production values:
public enum Supabase {
#if DEBUG
public static let url = "https://debug-project.supabase.co"
public static let anonKey = "DEBUG_KEY"
#else
// Production values (Release builds use this)
public static let url = "https://prod-project.supabase.co"
public static let anonKey = "PRODUCTION_KEY"
#endif
}
public enum RevenueCat {
#if DEBUG
public static let apiKey = "test_..."
#else
public static let apiKey = "appl_..." // Production key
#endif
}Verify no DEBUG flags in code:
# Search for DEBUG flags
grep -r "#if DEBUG" Src/
# Ensure no test/debug code will run in productionEnsure these are disabled in Release builds:
- Logging:
public enum Debug {
#if DEBUG
public static let enableLogging = true
#else
public static let enableLogging = false // OFF in production
#endif
}- Skip Onboarding (if you have a debug flag):
#if DEBUG
let skipOnboarding = false // Set to false
#endif- RevenueCat Debug Mode:
#if DEBUG
Purchases.logLevel = .debug
#else
Purchases.logLevel = .warn // Minimal logging in production
#endifIn Xcode:
- Click the device selector (next to scheme)
- Select Any iOS Device (arm64)
Note: You cannot archive for a specific simulator or device. Must be "Any iOS Device".
In Xcode:
- Product → Archive
- Wait for the archive to complete (5-15 minutes)
- The Organizer window will open automatically
Common Issues:
- "Archive is grayed out": Ensure "Any iOS Device" is selected
- Build fails: Check build errors, ensure all tests pass
- Signing error: Verify team is selected in Signing & Capabilities
Before uploading, validate the archive to catch issues early:
- In Organizer, select your archive
- Click Validate App
- Select Automatically manage signing (recommended)
- Click Validate
- Wait for validation to complete
Validation Checks:
- ✅ Code signing valid
- ✅ Provisioning profiles correct
- ✅ All required capabilities present
- ✅ No invalid frameworks
- ✅ App bundle structure correct
If validation fails: Fix the issues and create a new archive.
- In Organizer, select your archive
- Click Distribute App
- Select App Store Connect → Upload
- Select Automatically manage signing
- Click Upload
- Wait for upload to complete (5-20 minutes)
You'll receive an email when the build is processed (usually within 30 minutes).
TestFlight allows you to test your app before public release.
For your team (up to 100 testers):
- Go to App Store Connect
- Select your app → TestFlight tab
- Wait for build to finish processing
- Click on the build number
- Test Information section:
- What to Test: Describe what testers should focus on
- Beta App Description: Optional
- Add internal testers:
- Testers → Internal Group → +
- Add team members by email
- Click Save
Testers receive email invitation immediately.
For beta testers outside your team (up to 10,000 testers):
- In App Store Connect → TestFlight
- Select your build
- Click Add to External Testing
- Create a new group or select existing
- Add testers by email or public link
- Submit for Review (required for external testing)
Beta App Review:
- Required before external testers can access
- Similar to App Store review but faster (24-48 hours)
- Provide:
- Beta App Description
- What to Test
- Sign-in credentials (if app requires login)
For Testers:
- Install TestFlight app from App Store
- Accept invitation
- Install beta build
- Provide feedback via TestFlight or other channels
For Developers:
- Monitor crash reports in App Store Connect
- Respond to feedback quickly
- Iterate based on tester input
- Upload new builds as needed (increment build number)
All metadata is entered in App Store Connect:
- Select your app → App Information
Name:
- Display name on App Store
- Maximum 30 characters
- Must be unique
Subtitle (Optional but recommended):
- Short description (30 characters)
- Appears below app name
- Example: "Secure & Fast Authentication"
Privacy Policy URL:
- Required
- Must be accessible without login
- Example:
https://yourapp.com/privacy
Category:
- Primary: Choose most relevant
- Secondary: Optional
Content Rights:
- Contains third-party content: Yes/No
- If yes, need rights to use it
- Price: Free or paid (set price tier)
- Availability: All countries or specific regions
- App Release: Manual or automatic after approval
Privacy Details (Required):
- Data Collection: List all data your app collects
- User IDs, email, name, etc.
- Usage data, diagnostics, etc.
- Data Usage: How data is used
- Analytics, app functionality, advertising, etc.
- Data Linking: Is data linked to user identity?
- Tracking: Does app track users?
Example for this starter kit:
- Identifiers: Email, User ID (for account creation)
- Usage Data: Analytics (if using Firebase Analytics)
- Linked to User: Yes (for authentication)
- Tracking: No (unless you added third-party trackers)
Contact Information:
- First name, last name
- Phone number
Demo Account:
- Required if app requires login
- Provide username and password
- Ensure account has access to all features
Notes:
- Describe any special setup required
- Mention non-obvious features
- Explain compliance with guidelines
Example:
This app uses Supabase for backend and RevenueCat for subscriptions.
Test account credentials:
- Email: test@example.com
- Password: TestPassword123!
The app requires internet connection for authentication.
Subscription features can be tested using sandbox environment.
- Version:
1.0.0(must match your build) - Copyright: © 2025 Your Company Name
- Description (4000 characters):
- What the app does
- Key features
- Benefits to users
- Tip: Front-load important info (first 170 chars visible in search)
Example description:
Build amazing iOS apps faster with our production-ready starter kit.
KEY FEATURES:
• Secure authentication (Apple Sign-In & Google)
• In-app subscriptions with RevenueCat
• Supabase backend integration
• Push notifications
• Network monitoring
• App update checking
INCLUDED:
- Complete authentication flow
- Subscription management
- User profile system
- File upload with compression
- Modern SwiftUI architecture
- Event-driven communication
PERFECT FOR:
Developers who want to skip infrastructure setup and focus on unique features.
TECHNOLOGIES:
- SwiftUI
- Supabase
- RevenueCat
- Firebase
- Keywords (100 characters, comma-separated):
- Choose carefully (impacts search)
- No spaces around commas
- No duplicate words
Example:
ios,swift,swiftui,starter,boilerplate,template,authentication,subscription,supabase,revenuecat
- Promotional Text (170 characters, can be updated without new version):
Production-ready iOS template with auth, payments, and backend. Start building features on Day 1!
- What's New in This Version:
- For version 1.0.0:
Initial release! Features include:
• Apple Sign-In and Google authentication
• RevenueCat subscription management
• Supabase backend integration
• Push notifications
• Network monitoring
• Multi-page onboarding flow
Required Sizes:
| Device | Size | Required |
|---|---|---|
| 6.7" Display | 1290 × 2796 | ✅ Yes |
| 6.5" Display | 1242 × 2688 | ✅ Yes |
| 5.5" Display | 1242 × 2208 | ❌ No (but recommended) |
| iPad Pro (3rd gen) 12.9" | 2048 × 2732 | ✅ Yes (if iPad supported) |
| iPad Pro (2nd gen) 12.9" | 2048 × 2732 | ❌ No |
Best Practices:
- Show actual app features
- Use device frames
- Add captions explaining features
- First 2-3 screenshots most important (appear in search)
- Maximum 10 screenshots per device size
Tools:
- Shotbot - Generate screenshots with frames
- Screenshots.pro - Professional templates
- Figma - Design custom screenshots
Upload:
- In App Store Connect → Your App → App Store tab
- Media section
- Drag and drop screenshots for each device size
- Arrange in desired order
- In App Store Connect → App Store tab
- Scroll to Build section
- Click + to select a build
- Choose your uploaded build from TestFlight
- Click Done
Answer questionnaire about app content:
- Violence, profanity, horror, sexual content, etc.
- Be honest; incorrect rating can lead to rejection
- Most apps with just authentication: 4+
- Review all sections (look for red exclamation marks)
- Fix any missing required fields
- Click Save (top right)
- Click Submit for Review
- Confirm submission
Review Timeline:
- Typically 24-48 hours
- Can be longer during holidays or major iOS releases
- Check status in App Store Connect
Automate building and testing with GitHub Actions.
Create .github/workflows/ios.yml:
name: iOS CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
build-and-test:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '15.2'
- name: Install dependencies
run: |
# If using CocoaPods
# pod install
- name: Build for testing
run: |
xcodebuild clean build-for-testing \
-workspace iOSJumpstart.xcworkspace \
-scheme iOSJumpstart \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.2'
- name: Run tests
run: |
xcodebuild test-without-building \
-workspace iOSJumpstart.xcworkspace \
-scheme iOSJumpstart \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.2'Store sensitive data in GitHub repository secrets:
- Go to GitHub repository → Settings → Secrets and variables → Actions
- Click New repository secret
Required Secrets:
-
APPCONFIG_SWIFT: Base64-encodedAppConfiguration.swiftcat Src/Features/Common/Common/Configuration/AppConfiguration.swift | base64 -
GOOGLESERVICE_INFO_PLIST: Base64-encodedGoogleService-Info.plistcat Src/iOSJumpstart/iOSJumpstart/GoogleService-Info.plist | base64
Update workflow to decode secrets:
- name: Decode configuration files
env:
APPCONFIG_SWIFT: ${{ secrets.APPCONFIG_SWIFT }}
GOOGLESERVICE_INFO_PLIST: ${{ secrets.GOOGLESERVICE_INFO_PLIST }}
run: |
echo "$APPCONFIG_SWIFT" | base64 --decode > \
Src/Features/Common/Common/Configuration/AppConfiguration.swift
echo "$GOOGLESERVICE_INFO_PLIST" | base64 --decode > \
Src/iOSJumpstart/iOSJumpstart/GoogleService-Info.plistUse Fastlane for automated deployment:
- Install Fastlane:
brew install fastlane
cd your_project_directory
fastlane init- Configure Fastfile:
default_platform(:ios)
platform :ios do
desc "Build and upload to TestFlight"
lane :beta do
increment_build_number(xcodeproj: "Src/iOSJumpstart/iOSJumpstart.xcodeproj")
build_app(workspace: "iOSJumpstart.xcworkspace", scheme: "iOSJumpstart")
upload_to_testflight(skip_waiting_for_build_processing: true)
end
end- Add to GitHub Actions:
- name: Deploy to TestFlight
env:
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
run: |
fastlane betaCheck status:
- App Store Connect → Your App → App Store tab
- Status shows:
- Waiting for Review: In queue
- In Review: Apple is reviewing
- Rejected: Issues found (see Resolution Center)
- Pending Developer Release: Approved, awaiting your release
- Ready for Sale: Live on App Store
Respond to App Review:
- Check Resolution Center for messages
- Respond within 24 hours to avoid delays
- Provide requested information or clarifications
-
Incomplete Information:
- Missing demo account credentials
- Broken privacy policy URL
- Unclear app description
-
Guideline Violations:
- App crashes on launch
- Features don't work as described
- Missing required disclosures
-
Design Issues:
- Placeholder content
- Confusing user interface
- Poor user experience
If Rejected:
- Read rejection message carefully
- Fix the issues
- Reply in Resolution Center (if clarification needed)
- Upload new build (if code changes required)
- Resubmit
Manual Release:
- App Store Connect → Your App → Pricing and Availability
- Click Release this version
Automatic Release:
- Configured during submission
- App goes live immediately after approval
In App Store Connect:
- App Analytics: Downloads, sales, crashes
- Ratings and Reviews: User feedback
- Crash Reports: Diagnose issues
In RevenueCat Dashboard:
- Subscription metrics
- Revenue tracking
- Trial conversions
In Supabase Dashboard:
- User sign-ups
- Database usage
- API requests
Use this checklist for each release:
- All features tested
- Production credentials configured
- Version and build number updated
- Release notes written
- Screenshots updated (if UI changed)
- Privacy policy updated (if data collection changed)
- Release configuration selected
- Archive created successfully
- Archive validated without errors
- Uploaded to App Store Connect
- Build processed (received email)
- Internal testing completed
- Critical bugs fixed
- External beta testing (optional)
- Crash reports reviewed
- Metadata reviewed and updated
- Screenshots current
- What's New text written
- Build selected
- Age rating appropriate
- Demo account working
- All sections complete (no red marks)
- Submitted for review
- Monitoring review status
- Ready to respond to App Review
- Released to App Store
- Monitoring crash reports
- Tracking user feedback
- Planning next update
Follow Semantic Versioning:
Format: MAJOR.MINOR.PATCH
- MAJOR (1.0.0 → 2.0.0): Breaking changes, major redesign
- MINOR (1.0.0 → 1.1.0): New features, backwards compatible
- PATCH (1.0.0 → 1.0.1): Bug fixes, no new features
Examples:
- First release:
1.0.0 - Bug fix:
1.0.1 - New feature:
1.1.0 - Breaking change:
2.0.0
Auto-increment:
# Using agvtool (Apple's versioning tool)
agvtool next-version -allManual:
- Increment for each upload to App Store Connect
- Can reset to 1 for new version numbers
- Example: Version 1.0.0 builds: 1, 2, 3; Version 1.1.0 builds: 1, 2
- App Store Review Guidelines
- App Store Connect Help
- TestFlight Documentation
- Fastlane Documentation
- GitHub Actions for iOS
Ready to ship? Follow this guide step-by-step, and you'll have your app on the App Store! 🚀

