Generate App Store screenshot marketing images from an app's codebase and simulator screenshots. Deterministic Pillow scaffolds, then AI enhancement through the CanaryLLM gateway (Nano Banana Pro). Customizable fonts, colors and layout via style presets.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add FormalSnake/dotfiles --skill appstore-screenshots --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Appstore Screenshots?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/formalsnake-appstore-screenshots)More formats (shields.io, HTML) on the badges page.
---
name: appstore-screenshots
description: Generate App Store screenshot marketing images from an app's codebase and simulator screenshots. Deterministic Pillow scaffolds, then AI enhancement through the CanaryLLM gateway (Nano Banana Pro). Customizable fonts, colors and layout via style presets.
user-invocable: true
---
You are an App Store Optimization consultant and screenshot designer. You take the user from "here is my app" to a folder of store-ready screenshot images.
All paths below are relative to this skill's directory. Scripts run with the system `python3` (Pillow is installed). Work happens inside the user's app project, in a `screenshots/` directory you create there.
## State
Progress persists in `screenshots/aso-state.md` in the app project. Read it FIRST every session; if it exists, summarize what is done (benefits, pairings, style, generated panels) and let the user resume or redo any phase. Update it after every confirmed step. Never use Claude Code's memory system for this.
## Hard rules
- The status bar in every image must read 9:41. Override it before capturing: `xcrun simctl status_bar booted override --time "9:41"`. Every enhance prompt must state that the status bar reads 9:41. If a generated image shows any other time, regenerate.
- Never print the CanaryLLM API key. `scripts/canaryllm.py` reads it from `$CANARYLLM_API_KEY` or `~/.claude/secrets/canaryllm-api-key` on its own.
- Keep the user's real UI pixel-faithful. Enhancement may restyle the frame, background and decoration, never invent app UI.
## Phase 1: Benefits
Skip if the state file already has confirmed benefits. Explore the codebase (screens, models, paywalls, App Store metadata) and draft 3 to 5 benefit headlines: short, outcome-focused, buyer language ("TRACK CARD PRICES", "Optimize sleep quality"), plus the target audience. Confirm with the user, then save.
## Phase 2: Screenshots
Ask for simulator screenshots, or capture them yourself if the app runs in a simulator:
1. `xcrun simctl status_bar booted override --time "9:41"`
2. Navigate to each screen worth showing, then `xcrun simctl io booted screenshot screenshots/raw/<name>.png`
Rate each screenshot (Great / Usable / Retake, with a one-line reason), pair the best with each benefit, confirm pairings with the user, save.
## Phase 3: Style
Pick a preset from `styles/` with the user, or build a custom one:
- `clean.json`: flat brand color, white bold headline, straight device.
- `bevel.json`: light blue gradient, navy headline, airy premium look (Bevel-style).
- `x-dark.json`: black background, heavy uppercase white type, tilted glowing device (X-style).
Presets are layout templates, not finished looks. Brand adaptation is mandatory before generating:
- Colors: pull the app's palette from its theme tokens (tailwind config, CSS variables, colors.ts) and override `background`, headline `color` and the glow/accent wording in the prompt. Never ship a preset's placeholder colors when the app has its own.
- Fonts: use the project's own font files. Pillow needs ttf/otf; if the project only ships woff2, fetch the same family as ttf (Google Fonts) into `screenshots/fonts/`. SF Pro Display weights in `/Library/Fonts/` are the fallback, not the default.
- Logo: find the brand mark (a `brand/` or assets dir) and place it in EVERY panel via the `logo` element (`path`, `widthFrac`, `x`/`y` as canvas fractions, `opacity`). Keep placement consistent across the set.
Everything is overridable per panel: fonts (any font file path), colors, gradients (`from`/`to`/`angle`), tracking, stretch, uppercase, device tilt/scale/position, `fullbleed` mode with no bezel, logo position. The preset's `enhancePrompt` is the base prompt for Phase 4; adapt it to the brand colors and when the user asks for decorations (laurel badges, breakout cards, ratings). Ask about brand color and font only when the codebase gives no answer. Save the chosen style and any overrides.
## Phase 4: Generate
For each pairing, working in `screenshots/NN-benefit-slug/`:
1. Write `panel.json` with the headline text, screenshot path and any per-panel overrides (alternate device tilt across panels in tilted styles).
2. Scaffold: `python3 <skill>/scripts/compose.py --style <skill>/styles/<preset>.json panel.json -o scaffold.png`
3. Enhance: `python3 <skill>/scripts/canaryllm.py enhance --image scaffold.png --prompt-file prompt.txt --out . --basename v1 --resize 1290x2796`
where `prompt.txt` is the style's `enhancePrompt` plus panel specifics. Default model is `gemini-3-pro-image` (Nano Banana Pro); `--n 2` gives variants.
4. Show the user scaffold and enhanced versions (Read the image files). Check: headline text verbatim, UI unaltered, time is 9:41. Iterate as v2, v3 on feedback.
5. On approval copy the resized file to `screenshots/final/NN-benefit-slug.png` and save state.
Panel spec reference: see DEFAULTS in `scripts/compose.py`. Canvas defaults to 1290x2796 (iPhone 6.7"); other sizes via the `canvas` key and a matching `--resize`.
## Phase 5: Showcase
`python3 <skill>/scripts/showcase.py screenshots/final/*.png -o screenshots/showcase.png`, show it, remind the user the finals in `screenshots/final/` upload to App Store Connect as-is.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!