ios-app-store/SKILL.md
Help with App Store submission, TestFlight, CI/CD pipelines, Fastlane automation, and release management. Use when preparing for App Store release, setting up CI/CD, automating builds, creating screenshots, or debugging submission issues. Triggers on App Store, TestFlight, Fastlane, CI/CD, release, submit, screenshot, metadata, review, automation, GitHub Actions.
npx skillsauth add abanoub-ashraf/manus-skills-import ios-app-storeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert in iOS app distribution, App Store submission, and build automation. When this skill activates, help streamline the release process.
# Install via Homebrew
brew install fastlane
# Or via RubyGems
gem install fastlane
# Initialize in project
cd ios # or your iOS directory
fastlane init
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
# Before all lanes
before_all do
setup_ci if is_ci
end
# Run tests
desc "Run all tests"
lane :test do
run_tests(
scheme: "MyApp",
devices: ["iPhone 15"],
clean: true,
code_coverage: true
)
end
# Build for TestFlight
desc "Build and upload to TestFlight"
lane :beta do
increment_build_number(xcodeproj: "MyApp.xcodeproj")
build_app(
scheme: "MyApp",
export_method: "app-store",
output_directory: "./build",
output_name: "MyApp.ipa"
)
upload_to_testflight(
skip_waiting_for_build_processing: true,
changelog: changelog_from_git_commits
)
slack(message: "New beta build uploaded! 🚀") if is_ci
end
# Release to App Store
desc "Release to App Store"
lane :release do
ensure_git_status_clean
ensure_git_branch(branch: "main")
increment_version_number(bump_type: "patch")
increment_build_number
build_app(
scheme: "MyApp",
export_method: "app-store"
)
upload_to_app_store(
submit_for_review: true,
automatic_release: true,
force: true,
precheck_include_in_app_purchases: false
)
commit_version_bump
add_git_tag
push_to_git_remote
end
# Screenshots
desc "Capture screenshots"
lane :screenshots do
capture_screenshots(
scheme: "MyAppUITests",
devices: [
"iPhone 15 Pro Max",
"iPhone 15",
"iPhone SE (3rd generation)",
"iPad Pro (12.9-inch) (6th generation)"
],
languages: ["en-US", "es-ES", "de-DE"],
clear_previous_screenshots: true
)
frame_screenshots(white: true)
upload_to_app_store(skip_binary_upload: true)
end
end
# fastlane/Matchfile
git_url("[email protected]:yourteam/certificates.git")
storage_mode("git")
type("appstore")
app_identifier(["com.company.app", "com.company.app.widget"])
username("[email protected]")
# For CI
readonly(is_ci)
# fastlane/Appfile
app_identifier("com.company.app")
apple_id("[email protected]")
itc_team_id("123456789")
team_id("ABCDEF1234")
# .github/workflows/ios.yml
name: iOS CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: macos-14
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Cache SPM
uses: actions/cache@v4
with:
path: .build
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
- name: Build
run: |
xcodebuild build \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 15' \
-configuration Debug \
CODE_SIGNING_ALLOWED=NO
- name: Test
run: |
xcodebuild test \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 15' \
-resultBundlePath TestResults.xcresult \
CODE_SIGNING_ALLOWED=NO
- name: Upload Test Results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: TestResults.xcresult
# .github/workflows/testflight.yml
name: Deploy to TestFlight
on:
push:
branches: [main]
jobs:
deploy:
runs-on: macos-14
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Install Fastlane
run: brew install fastlane
- name: Setup Signing
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_TOKEN }}
run: fastlane match appstore --readonly
- name: Build and Upload
env:
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.ASC_KEY_ID }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_PRIVATE_KEY }}
run: fastlane beta
- name: Notify Slack
if: success()
run: |
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"iOS build deployed to TestFlight! 🚀"}' \
${{ secrets.SLACK_WEBHOOK_URL }}
# In Fastfile or Appfile
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_content: ENV["ASC_PRIVATE_KEY"],
is_key_content_base64: true
)
# Encode the .p8 file
base64 -i AuthKey_XXXXXXXXXX.p8 | pbcopy
# Add to GitHub Secrets as ASC_PRIVATE_KEY
// SnapshotHelper.swift is added automatically
// In your UI test:
func testScreenshots() {
let app = XCUIApplication()
setupSnapshot(app)
app.launch()
// Navigate and capture
snapshot("01-HomeScreen")
app.buttons["Settings"].tap()
snapshot("02-Settings")
app.buttons["Profile"].tap()
snapshot("03-Profile")
}
# fastlane/Snapfile
devices([
"iPhone 15 Pro Max",
"iPhone 15",
"iPhone SE (3rd generation)",
"iPad Pro (12.9-inch) (6th generation)"
])
languages([
"en-US",
"es-ES",
"de-DE",
"ja"
])
scheme("MyAppUITests")
output_directory("./screenshots")
clear_previous_screenshots(true)
concurrent_simulators(true)
# fastlane/Deliverfile
app_identifier("com.company.app")
username("[email protected]")
# Metadata
name({
"en-US" => "My Amazing App",
"es-ES" => "Mi Aplicación Increíble"
})
subtitle({
"en-US" => "The best app ever",
"es-ES" => "La mejor aplicación"
})
# Screenshots from directory
screenshots_path("./screenshots")
# App Review Information
app_review_information(
first_name: "John",
last_name: "Doe",
phone_number: "+1 555-1234",
email_address: "[email protected]",
demo_user: "[email protected]",
demo_password: "demo123",
notes: "Use the demo account to test all features."
)
# Submission
submit_for_review(true)
automatic_release(false)
# Phased release
phased_release(true)
fastlane/metadata/
├── en-US/
│ ├── name.txt
│ ├── subtitle.txt
│ ├── description.txt
│ ├── keywords.txt
│ ├── release_notes.txt
│ ├── privacy_url.txt
│ ├── support_url.txt
│ └── marketing_url.txt
├── es-ES/
│ └── ... (same files)
└── review_information/
├── first_name.txt
├── last_name.txt
└── ...
# In Fastfile
lane :bump_patch do
increment_version_number(bump_type: "patch")
increment_build_number
commit_version_bump(xcodeproj: "MyApp.xcodeproj")
end
lane :bump_minor do
increment_version_number(bump_type: "minor")
increment_build_number
commit_version_bump(xcodeproj: "MyApp.xcodeproj")
end
lane :bump_major do
increment_version_number(bump_type: "major")
increment_build_number
commit_version_bump(xcodeproj: "MyApp.xcodeproj")
end
| Issue | Solution | |-------|----------| | Missing privacy manifest | Add PrivacyInfo.xcprivacy with required API reasons | | ITMS-90683: Missing Purpose String | Add NSCameraUsageDescription, etc. to Info.plist | | Missing 6.5" screenshots | Add iPhone 15 Pro Max screenshots | | Incomplete metadata | Fill all required App Store Connect fields | | Crashes during review | Test on real devices, check crash logs |
<!-- PrivacyInfo.xcprivacy -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
development
Design principles for building polished, native-feeling SwiftUI apps and widgets. Use this skill when creating or modifying SwiftUI views, iOS widgets (WidgetKit), or any native Apple UI. Ensures proper spacing, typography, colors, and widget implementations that look and feel like quality apps rather than AI-generated slop.
data-ai
Design and implement SwiftUI views, components, and app architecture. Use when creating new SwiftUI views, implementing MVVM/TCA patterns, managing state with @Observable, @State, @Binding, or @Environment, designing navigation flows, or structuring iOS app architecture. Triggers on SwiftUI, view model, state management, navigation, coordinator pattern.
development
Implement, review, or improve SwiftUI animations and transitions. Use when adding implicit or explicit animations with withAnimation, configuring spring animations (.smooth, .snappy, .bouncy), building phase or keyframe animations with PhaseAnimator/KeyframeAnimator, creating hero transitions with matchedGeometryEffect or matchedTransitionSource, adding SF Symbol effects (bounce, pulse, variableColor, breathe, rotate, wiggle), implementing custom Transition or CustomAnimation types, or ensuring animations respect accessibilityReduceMotion.
testing
Audit SwiftUI views for accessibility (iOS + macOS) with patch-ready fixes