Maintenance
Automation lives in the scripts/ package (swpngx) and
fastlane/. Run swpngx via uv run --project scripts swpngx …
from the repo root (or install the package so swpngx is on your PATH).
Device ids, simulator names, bezel PNGs, and framing geometry are defined once in
screenshot_devices.toml. screenshots.toml
references those ids for capture; frames.toml references the same file
for framing. iPhone screenshots use Pro Max only (App Store Connect scales for smaller
phones). Check alignment with:
console
uv run --project scripts swpngx devices check
App Store screenshots
1. Capture raw simulator PNGs (config: screenshots.toml):
```console uv run --project scripts swpngx capture setup
Or pin the screenshot backend:
uv run --project scripts swpngx capture setup --pngx-tag 2.19.4
Or add random tags for UI stress testing:
uv run --project scripts swpngx capture setup --random-tags 1000
Or add multiple random metadata types:
uv run --project scripts swpngx capture setup --random-tags 1000 --random-correspondents 500 --random-document-types 250 uv run --project scripts swpngx capture capture ```
Writes files like fastlane/screenshots/en-US/iPhone_17_Pro_Max-01_documents.png
(the prefix is the device id from screenshot_devices.toml). Tear down the backend
with uv run --project scripts swpngx capture teardown.
2. Install device bezels from Apple Design Resources
(Product Bezels). Each [[device]] in screenshot_devices.toml
names a bezel_pack from bezel_packs.toml and the PNG filename
to install under fastlane/screenshots/frames/:
```console
Use DMGs you already downloaded (e.g. from ~/Downloads):
uv run --project scripts swpngx frames download --dmg-dir ~/Downloads
Or let swpngx download from Apple into ~/Library/Caches/swpngx/bezels:
uv run --project scripts swpngx frames download
Only the iPhone 17 pack, with one DMG path:
uv run --project scripts swpngx frames download --pack iphone_17 \ --dmg-path ~/Downloads/Bezel-iPhone-17.dmg ```
Requires macOS (hdiutil). Apple’s DMG license prompt is accepted automatically
(Y); you must comply with the Apple Design Resources license.
3. Frame screenshots for the App Store (config: frames.toml):
console
uv run --project scripts swpngx frame
Reads fastlane/screenshots/<locale>/, composites device bezels and localized
titles (from fastlane/screenshots/Screenshots.xcstrings),
and writes fastlane/screenshots/framed/<locale>/*-framed.png. Device names in
filenames must match device id in screenshot_devices.toml.
The framing font (Open Sans) is not in git (fastlane/.gitignore ignores *.ttf).
swpngx frame downloads it automatically from Google Fonts
via fonts.toml, or you can prefetch:
console
uv run --project scripts swpngx fonts download
Preview locally:
console
uv run --project scripts swpngx preview
4. Upload metadata and framed screenshots with deliver
(config: fastlane/Deliverfile):
console
just deliver-preview # dry run
just deliver # metadata + screenshots
just deliver-metadata # metadata only (What's New, description, …)
just deliver uploads both metadata and screenshots in one fastlane deliver
run (not a separate command). It uses MARKETING_VERSION from
Config/Shared/Version.xcconfig, replaces all screenshots, and reads metadata
from fastlane/metadata/.
What's New is edited only in fastlane/metadata/default/release_notes.txt.
The Deliverfile reads that once and applies it to every metadata locale (including
en-US, which App Store Connect does not fill from default/ on its own).
Before uploading:
- Edit fastlane/metadata/default/release_notes.txt for the new version.
skip_binary_upload is enabled in the Deliverfile, so this uploads metadata and
screenshots only (no IPA). TestFlight builds use just beta / fastlane beta
separately.
Authentication uses the same App Store Connect API key as TestFlight
(APP_STORE_CONNECT_API_KEY_ID, APP_STORE_CONNECT_ISSUER_ID, and
APP_STORE_CONNECT_KEY_FILEPATH or APP_STORE_CONNECT_KEY_CONTENT), plus
APPLE_ID, ITC_TEAM_ID, and TEAM_ID from fastlane/Appfile.
PNG screenshots under fastlane/screenshots/ are gitignored; generate them locally
before upload.
There is also bundle exec fastlane screenshots (snapshot + fastlane/Snapfile),
a UI-test-based path that is separate from the swpngx workflow above.
Panorama montage
Concatenate framed screenshots (adjust the glob for your device name):
console
montage fastlane/screenshots/framed/en-US/iPhone_17_Pro_Max-01_*-framed.png \
-tile 4x1 -geometry +20+0 panorama.png