iOS Marketing Capture Automation
Skill by ara.so — Marketing Skills collection.
What This Skill Does
This skill helps you automate marketing screenshot capture for SwiftUI iOS apps by building an in-app capture system that:
- Adds a
#if DEBUG-gated capture system with zero production footprint - Seeds deterministic demo data so screenshots look populated and polished
- Navigates to each screen programmatically via step-based coordinator
- Snapshots full window including status bar, safe area, and presented sheets
- Renders isolated elements (cards, widgets, charts) via
ImageRendererat 3x with transparency - Loops every locale automatically — one build, N relaunches with
-AppleLanguages - Works with any SwiftUI navigation:
TabView,NavigationStack,NavigationSplitView
Installation
Using npx skills (recommended)
Global install (available across all projects):
Agent-specific install:
Manual installation
Requirements Checklist
Before starting, verify:
- ✅ Xcode 16+ (synchronized folder groups support)
- ✅ iOS 17+ deployment target (for
ImageRenderer,@Observable) - ✅ A simulator runtime matching target iOS version
- ✅ Python 3 (for JSON parsing in shell script)
- ✅ SwiftUI-based app with defined navigation structure
Core Concepts
In-App Capture (Not XCUITest)
This approach uses in-app capture instead of XCUITest/Fastlane because:
- No test target needed — many projects lack one, adding means fragile pbxproj edits
- Direct access — ViewModels, SwiftData,
ImageRenderer,UIWindow.drawHierarchy - Faster —
xcodebuild buildonce, thensimctl launchper locale - Element renders require it —
ImageRenderermust run inside app process
Step-Based Coordinator
Each screenshot is a self-contained CaptureStep:
Implementation Pattern
1. Gather Requirements
When user asks to capture screenshots, collect:
- Screens to capture — exact tab names or navigation paths
- Elements to render — cards, widgets, charts to isolate
- Locales — explicit list or "all locales in xcstrings"
- Device — simulator model (e.g. "iPhone 17")
- Appearance — light, dark, or both
- Seed data requirements — what demo data needs to populate
2. Generated File Structure
Create this structure:
Output lands in:
3. Core Capture System Code
4. Navigation Pattern Examples
TabView Navigation
NavigationStack with Router
NavigationSplitView
5. Demo Data Seeding
6. Integrating with ContentView
7. Element Rendering Examples
Widget Rendering
Card Rendering
Chart Rendering
8. Build and Launch Script
Critical Gotchas (Baked Into Skill)
1. Live Activities Persist Across Launches
Problem: Next locale crashes on stale SwiftData references.
Solution: End all Live Activities in cleanup:
2. Re-Seeding Per Locale
Problem: CloudKit sync churn causes crashes.
Solution: Seed once at launch, not per step.
3. ViewModels Setup Before Seed
Problem: VMs hold stale empty snapshots.
Solution: Seed data → wait 1s → instantiate VMs → capture.
4. Setting Trigger Binding to nil
Problem: Doesn't dismiss fullScreenCover — captures wrong sheet.
Solution: Use dedicated dismiss closure:
5. NavigationPath Can't Be Popped Externally
Problem: Pushing over existing path captures wrong stack.
Solution: Always popToRoot() before push() in navigate block.
6. membershipExceptions Is an INCLUSION List
Problem: Widget target membership goes backwards — widget renders fail.
Solution: Set membershipExceptions for DEBUG files to exclude widget target:
7. ImageRenderer + ProgressView
Problem: Renders as prohibited symbol without explicit style.
Solution: Force .circular style:
8. .containerBackground Outside WidgetKit
Problem: No-op — widget renders have no background.
Solution: Manually add background in render harness:
9. iPhone 8 Plus Gone on iOS 18+
Problem: Legacy 6.5" simulator unavailable.
Solution: Use iPhone 17 Pro Max or latest available large device.
10. Locale Launch Argument Format
Problem: Locale ignored if parens missing.
Solution: Always use "($LOCALE)" format:
11. SwiftUI Animations in ImageRenderer
Problem: Captures frame 0, not animated state.
Solution: Render non-animated state or use explicit .animation(nil).
Common Workflows
Capturing Timer Mid-Countdown
Capturing Presented Sheet
Rendering All Widgets
Troubleshooting
Capture exits immediately
Check: MARKETING_CAPTURE=1 env var is set in launch args.
Locale not applied
Check: Parens in -AppleLanguages:
Widget renders blank
Check: Manual padding added (WidgetKit adds 16pt automatically):
Screenshot captures wrong screen
Check: Settle duration long enough for animations:
SwiftData crash on second locale
Check: Live Activities ended in cleanup:
Element renders with wrong size
Check: Frame width explicitly set:
Configuration Reference
Capture Step Properties
Script Variables
Environment Variables
Set in launch args or script:
Post-Processing
Use app-store-screenshots to composite captured PNGs into Apple-style marketing pages with device mockups, headlines, and gradients.
Then prompt:
When to Use This Skill
✅ Use when:
- Capturing marketing screenshots for App Store
- Rendering isolated components (cards, widgets, charts)
- Multi-locale asset generation
- SwiftUI-based iOS app with defined navigation
- Need full control over demo data and app state
❌ Don't use when:
- UIKit-based app (requires different capture approach)
- XCUITest infrastructure already working well
- Single locale, manual capture sufficient
- App uses web views or external content (can't seed)
Example: Complete Coffee App Capture
Run:
Output:
Summary
This skill automates iOS marketing screenshot capture by:
- Gathering requirements — screens, elements, locales, device, appearance
- Generating capture system — DEBUG-gated coordinator + steps
- Seeding demo data — deterministic, locale-agnostic
- Navigating programmatically — TabView, NavigationStack, or SplitView
- Capturing window —
drawHierarchyfor full screenshots - Rendering elements —
ImageRendererfor isolated components - Looping locales —
simctl launchwith-AppleLanguages
The result: one build, N launches, complete multi-locale marketing assets ready for App Store or further compositing.

