Create and refine App Store screenshot sets from an app codebase plus existing app screenshots. Use when Codex needs to discover ASO benefit headlines, review and rate supplied screenshots, pair screens to messages, choose colors and typography, compose App Store-ready PNGs, or build a showcase image without Figma or simulator automation.
Resources
7Install
npx skillscat add aruffolo/codex-skill-aso-appstore-screenshots Install via the SkillsCat registry.
ASO App Store Screenshots
Work from screenshots the user already has. Do not assume simulator control. Build a deterministic scaffold first, then optionally polish it with any image-generation tool the user explicitly asks to use.
This skill is a Codex adaptation of Adam Lyttle's original Claude skill, claude-skill-aso-appstore-screenshots. Preserve that attribution when redistributing substantial copies or adaptations.
Core Workflow
1. Build product context
Inspect the app codebase, metadata, and any existing marketing copy to answer:
- What the app does
- Who it is for
- Why it is better than alternatives
Ask only the missing market questions. Keep the discussion focused on conversion, not feature inventory.
2. Discover the screenshot messages
Draft 3 to 5 benefit headlines. Each should:
- start with an action verb
- describe a user outcome, not an implementation detail
- map to a screen the user can actually show
Good pattern:
TRACK EVERY BOTTLEPLAN PREP AHEADFOLLOW EVERY TIMELINE
Bad pattern:
ADVANCED ANALYTICSMODERN UIPOWERFUL FEATURES
Do not move on until the user confirms the headline list and order.
3. Review the provided screenshots
Accept:
- a directory
- explicit file paths
- a glob pattern
Open every candidate screenshot. Rate each one:
GreatUsableRetake
For every screenshot, say:
- what it shows
- what works
- what does not work
- the verdict
Check for:
- empty or low-content states
- debug UI
- weak hierarchy at thumbnail size
- clipped key content
- inconsistent light/dark mode
- noisy status bar
- generic or low-conviction screens like settings, onboarding, or sparse lists when a stronger screen exists
Give blunt retake guidance when needed. The goal is conversion, not coverage.
If any screenshot is Retake, do not hand-wave. Give an explicit retake plan:
- which screen to capture instead
- which app state or seeded data to show
- whether to retake in light or dark mode for consistency
- what visual clutter to remove
- what the screenshot must prove at thumbnail size
- whether simulator capture is recommended to get a cleaner result
When coaching simulator retakes, be concrete:
- name the exact screen to open
- name the exact data density to show
- call out status bar cleanup
- reject empty states unless the whole app is about empty-state onboarding
Persist retake guidance in appstore-screenshots/state/retake-plan.md when needed.
4. Pair screenshot to headline
For each confirmed headline, pick the best screenshot. Prioritize:
- direct relevance
- strong visual density
- quick comprehension at thumbnail size
- variety across the set
If a headline has no strong screenshot, say so and stop for retakes instead of forcing a weak pairing.
5. Lock design direction
Before composing, confirm:
- primary background color
- optional accent color
- font choice
- tone: minimal, premium, energetic, clinical, playful
Defaults:
- title font:
SF Pro Display Blackif installed - subtitle font:
SF Pro Display Blackif installed - device frame: generated by
scripts/generate_frame.pywithout Dynamic Island by default - export size:
1290x2796unless the user wants a different App Store target
If branding is unclear, propose one primary color plus one fallback and explain which direction converts better.
6. Compose deterministic scaffolds
Use the bundled scripts:
scripts/generate_frame.pyto regenerate the reusable device frame assetscripts/compose.pyto build each screenshotscripts/showcase.pyto assemble a quick preview strip
Recommended output structure inside the user project:
appstore-screenshots/
state/
benefits.md
screenshot-review.md
pairings.md
design-direction.md
retake-plan.md
style-template.md
polish-decisions.md
work/
01-benefit-slug/
scaffold.png
v1.png
v2.png
v3.png
v1-resized.png
v2-resized.png
v3-resized.png
02-benefit-slug/
scaffold.png
final/
01-benefit-slug.png
02-benefit-slug.png
showcase.pngAlways persist state files in the project so work can resume in a later Codex session without rediscovery.
7. Optional polish
If the user explicitly wants AI polish and Gemini MCP or equivalent Gemini-compatible image editing is available, use the scaffold as the source of truth:
- preserve text hierarchy
- preserve screenshot content
- preserve frame placement
- ask for small visual polish, not a redesign
Never skip the deterministic scaffold. It is the recovery path.
Before running Gemini polish:
- state clearly that Gemini polish is optional
- state that Gemini usage may incur API charges
- confirm deterministic mode remains the fallback if Gemini tooling is unavailable
When the user wants Gemini polish:
- Create the deterministic scaffold first.
- For the first benefit, generate 3 polished variants from the scaffold.
- Crop or resize every polished variant to the final App Store export size before review.
- Ask the user to pick a winner.
- Save the winning polished slide path and its visual treatment in
appstore-screenshots/state/style-template.md. - For later benefits, keep the new scaffold layout and screenshot content, but match the approved visual treatment from the saved style template.
- When iterating, generate 3 new variants again unless the user asks for fewer.
Persist Gemini decisions in appstore-screenshots/state/polish-decisions.md:
- whether Gemini polish was enabled
- which provider/tooling was available
- which slide was chosen as the style template
- any locked visual constraints for later slides
If Gemini tooling is missing, stop at the deterministic scaffold and say exactly what integration is missing.
8. Final review
Before declaring done, check:
- message order makes narrative sense
- typography consistent across all slides
- screenshot crops show the intended feature clearly
- backgrounds consistent
- final files open at the requested export size
File Guidance
Load workflow.md when you need the detailed rating rubric, naming rules, or composition checklist.
Load gemini-polish.md when the user explicitly wants AI polish or when you need the detailed Gemini variant workflow.
Commands
Generate or refresh the frame:
python3 ~/.codex/skills/aso-appstore-screenshots/scripts/generate_frame.pyGenerate an optional Dynamic Island frame:
python3 ~/.codex/skills/aso-appstore-screenshots/scripts/generate_frame.py --dynamic-islandCompose one screenshot:
python3 ~/.codex/skills/aso-appstore-screenshots/scripts/compose.py \
--bg "#8C3D1B" \
--verb "TRACK" \
--desc "EVERY BOTTLE" \
--screenshot path/to/screen.png \
--output appstore-screenshots/work/01-track-every-bottle/scaffold.pngOpt in to a Dynamic Island frame:
python3 ~/.codex/skills/aso-appstore-screenshots/scripts/compose.py \
--bg "#8C3D1B" \
--verb "TRACK" \
--desc "EVERY BOTTLE" \
--screenshot path/to/screen.png \
--dynamic-island \
--output appstore-screenshots/work/01-track-every-bottle/scaffold.pngCreate a showcase:
python3 ~/.codex/skills/aso-appstore-screenshots/scripts/showcase.py \
--screenshots appstore-screenshots/final/01-track-every-bottle.png appstore-screenshots/final/02-plan-ahead.png \
--output appstore-screenshots/showcase.pngBoundaries
- Do not invent features that the product cannot show.
- Do not write generic marketing lines when the screen can support something more specific.
- Do not force every screenshot to use the same layout if the user asks for variation, but keep one consistent system unless asked otherwise.
- Do not require Figma. Use code first.
- Do not imply Gemini polish is free; call out that API charges may apply.
- Do not run AI polish by default; deterministic scaffolds stay the default path.