CommunityBildgithub.com

meth0xy/store-screenshots

Erstellt deterministische App-Store- und Google-Play-Screenshot-Sets als Daten, nicht als generierte Bilder. Findet die Vorteile der App im Code, erstellt echte Screenshots aus iOS-Simulatoren und Android-Emulatoren und rendert sie in jeder Sprache und auf jedem Gerät mit Playwright.

Was ist store-screenshots?

Diese Fähigkeit ermöglicht die professionelle Erstellung von App-Store- und Google-Play-Screenshot-Sets auf Datenbasis. Der Prozess beginnt mit der Extraktion der Hauptvorteile der App aus dem Codebase, gefolgt von der Aufnahme echter Screenshots aus iOS-Simulatoren und Android-Emulatoren (iPhone, iPad, iPhone Duo, Android-Phone und -Tablet). Jeder Screenshot wird auf einer HTML-Leinwand mit Geräterahmen, Überschriften und Callouts aus lokalisierten JSON-Dateien komponiert. Das System unterstützt mehrere Sprachen und Geräte, wobei jedes Textstring in `locales/<locale>.json` lebt – eine neue Sprache benötigt nur eine JSON-Datei und die entsprechenden Aufnahmen. Die deterministische Render-Pipeline stellt sicher, dass gleiche Eingaben identische Pixel liefern. Die Fähigkeit ist plattformübergreifend einsetzbar: Sie unterstützt iOS (Simulatoren) und Android (Emulatoren) und funktioniert mit Cross-Plattform-Frameworks wie React Native und Flutter, wobei Android-Tiles standardmäßig iPhone- und iPad-Aufnahmen wiederverwenden. Native Android-Apps können eigene Screenshots über separate Verzeichnisse beisteuern. Der Workflow gliedert sich in klare Schritte: Vorteile analysieren, Slides definieren, Aufnahmen planen und durchführen, Komposition in `set.json` beschreiben und mit Playwright rendern. Die Ausgabe erfolgt als store-konforme Bilder plus Kontaktbögen zur Qualitätskontrolle. Der gesamte Prozess ist repetierbar und versionierbar, sodass Screenshot-Sets wie Code verwaltet werden können. Der Benutzer interagiert hauptsächlich über die Kommandozeile (Python-Skripte für Capture, Render, Locale-Verwaltung) und konfiguriert Projekte über JSON-Dateien (`capture.json`, `set.json`, `locales/<locale>.json`). Die Fähigkeit stellt sicher, dass alle Texte und UI-Elemente exakt bleiben und dass neue Sprachen oder Geräte ohne Neuerfindung des gesamten Sets hinzugefügt werden können.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/meth0xy/store-screenshots/tree/HEAD/skills/store-screenshots

Installed? Explore more Bild skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Du erstellst Store-Screenshot-Sets als Daten, nicht als generierte Bilder. Jedes Tile ist eine HTML-Leinwand mit mehreren Ebenen: Hintergrund, Überschrift, ein Geräterahmen mit einem echten Screenshot und Breakouts (Ausschnitte des Screenshots oder vektorbasierte Callouts), die in 3D aus dem Bild herausgehoben sind. Jeder Text lebt in locales/<locale>.json, sodass eine neue Sprache nur eine JSON-Datei plus Aufnahmen benötigt, und der Render-Vorgang ist deterministisch: gleiche Eingaben erzeugen die gleichen Pixel.

$S unten ist der Ordner, in dem diese SKILL.md liegt, $PY ist $S/.venv/bin/python. Wenn die virtuelle Umgebung fehlt, erstelle sie einmalig:

python3 -m venv $S/.venv && $S/.venv/bin/pip install -r $S/requirements.txt && $S/.venv/bin/playwright install chromium

Pipeline:

1 benefits -> 2 slides -> 3 capture.json -> 4 capture (simulators) -> 5 composition
-> 6 background -> 7 set.json + locales -> 8 render -> 9 review -> (more languages, devices)

$S/../../examples/demo/ im Repository ist ein vollständiges Projekt (fiktive App, zwei Sprachen, fünf Geräte). Lies dessen set.json, bevor du eines schreibst.

Projektstruktur

<project>/
  capture.json                  App, Aufnahmegeräte, zu erfassende Bildschirme
  set.json                      Composition, die von allen Sprachen geteilt wird
  locales/<locale>.json         Jeder Text: Verb, Unterzeile, Callout-Texte
  sim/<locale>/<slide>.png      Screenshots (ein Ordner pro Aufnahmeset)
  sim-tablet/  sim-duo/  sim-android/
  fonts/  assets/               Optionale Schriftarten, Hintergrundbild, Objekte
  out/<locale>/<device>/        Nur Store-Dateien
  out/_sheets/                  Kontaktbogen pro Sprache und Gerät
  out/_captures/                Kontaktbogen pro Sprache nach der Aufnahme

Empfehle store-screenshots/ im Stammverzeichnis der App. Füge out/ und .cache/ zu dessen .gitignore hinzu.


1. Benefits (Vorteile)

Lies das Codebase: Navigation (Tabs, Routen, Bildschirme), Onboarding-Texte, Paywall-Texte, README, vorhandene Store-Listings. Liste die 5 bis 8 Dinge auf, die ein Benutzer erhält, sortiert danach, wie sehr sie eine Installation fördern würden. Ein Vorteil pro Slide.

Jede Slide-Überschrift besteht aus einem kurzen Verb in Großbuchstaben und einer Unterzeile von maximal zwei Zeilen: PLAN / YOUR WEEK IN MINUTES, SAVE / ON EVERY SHOP. Das Verb benennt den Vorteil, nicht die Funktion. Zeige die Liste mit dem Bildschirm, der jeden Vorteil belegt, und hole eine Bestätigung ein.

2. Slides

ID NN-name; die Zahl ist die Position im Store. Wähle den Bildschirm pro Slide und notiere den benötigten Zustand (eingeloggt, Daten vorhanden, ein Sheet offen). Neige bildlastige Bildschirme, behalte datenreiche Bildschirme gerade.

3. capture.json

Beginne mit $S/templates/capture.json.

SchlüsselBedeutung
app.iosbundleId und app (Pfad zu einem Simulator-.app-Build) oder copyFrom (UDID eines Simulators, auf dem es installiert ist)
app.androidpackage, optional activity, optional apk zum Installieren
devices.<key>platform ios oder android, dir (Aufnahmeordner), iOS: name (dedizierter Simulator, durch Setup erstellt) und type (xcrun simctl list devicetypes), optional runtime; Android: avd (emulator -list-avds)
Device-Extrasappearance (light), locale (überschreibt den untenstehenden Modus), displaySize (2853x2007 wählt das innere Display des iPhone Duo), rotate (Grad, für Aufnahmen, die seitlich erscheinen)
localePro Plattform. iOS reboot (Standard, zuverlässig), relaunch (kein Neustart, behält die Pose eines Foldables) oder launchArgs. Android app (Standard, sprachspezifisch ab Android 13, benötigt localeConfig der App) oder system (benötigt ein root-fähiges Emulator-Image)
launchwait Sekunden nach dem Start, optional url zum Öffnen anstelle des App-Starts (Expo-Dev-Client-URL), optional steps
screensListe von {id, steps, ready, after, devices, copyFrom}, plus byDevice- / byLocale-Blöcke, die über den Screen gemerged werden

Schritte werden der Reihe nach ausgeführt und warten jeweils (wait, Standard 1 bis 2 s):

SchrittEffekt
{"open": "myapp://route"}Deep Link. Bevorzuge dies gegenüber Taps: es funktioniert auf jedem Gerät und jeder Plattform
{"tap": {"label": "Save"}}Tippt auf das Element mit diesem Accessibility-Label (oder {"id": ...}), exakt dann Substring-Suche
{"tap": {"at": [0.5, 0.9]}}Tippt auf eine Position als Bruchteil des Bildschirms
{"tap": {...}, "until": {"label": "Details"}}Tippt erneut (bis zu 3 Mal), bis dieses Element erscheint; verwende es bei Taps auf Bildschirmen, die noch nicht stabil sind
{"waitFor": {"label": "Done", "timeout": 20}}Wartet, bis ein Element auf dem Bildschirm ist, vor Taps auf Bildschirmen, die laden oder animieren
{"type": "pasta"}, {"key": "enter"}, {"key": "back"}Text und Tasten
{"swipe": [0.5, 0.8, 0.5, 0.3]}Wischen, Bruchteile
{"launch": true}App neu starten

ready: {"region": [x, y, w, h], "minStd": 20, "tries": 5, "delay": 3} wiederholt Aufnahmen, während dieser Bereich eine einfarbige Farbe zeigt (Skeleton-Zeilen, ein Spinner, ein noch ladendes Bild). iPhone-Aufnahmen werden automatisch wiederholt, wenn der Simulator die Dynamic Island in sie einbrennt.

copyFrom: "01-home" verwendet eine andere Aufnahme auf diesem Gerät (ein Tablet zeigt zwei Bildschirme in einer geteilten Ansicht). devices: ["phone"] beschränkt einen Bildschirm auf einige Geräte.

capture.py PROJEKT describe --device phone gibt tappbare Elemente mit Labels und Rahmen aus.

4. Aufnahme (Capture)

$PY $S/capture.py <project> doctor              # Werkzeuge, Geräte, App-IDs
$PY $S/capture.py <project> setup               # Erstellen/Starten dedizierter Simulatoren, Starten von AVDs, Installieren der App
$PY $S/capture.py <project> run --locale en-US  # Jedes Gerät und jeder Bildschirm
$PY $S/capture.py <project> run --locale en-US --device phone --screen 03-search
  • Aufnahmegeräte sind dediziert: iOS-Simulatoren werden mit Namen erstellt (Capture iPhone ...), Android verwendet die in capture.json benannten AVDs. Richte capture.json niemals auf den Simulator, in dem der Benutzer arbeitet, und frage nach, bevor du Geräte startest oder deren Sprache wechselst.
  • Nach setup benötigt die App normalerweise einen Demo-Zustand: Anmeldung bei einem Demo-Konto, Seed-Daten, erste Dialoge schließen (Passwort speichern, Benachrichtigungen, Bewertungsaufforderungen). Mache dies einmal pro Gerät; der Zustand bleibt über Sprachwechsel hinweg erhalten. Frage den Benutzer nach Demo-Anmeldedaten, schreibe sie niemals in capture.json.
  • Ein Dev-Build, der Debug-Overlays anzeigt (Dev-Menü-Buttons, Toasts), muss diese für die Aufnahme-Session verstecken. Entferne sie lokal und committe den Patch nicht.
  • Überprüfe out/_captures/<locale>.jpg Tile für Tile: kein Text in einer anderen Sprache, kein Dialog, Toast, Spinner oder leerer Zustand. Korrigiere Daten oder Schritte und führe diesen Bildschirm erneut aus. Der Renderer zeigt die Aufnahme so, wie sie ist; nichts übermalt einen Fehler.
  • iPhone Duo: Entfalte den Simulator und lege ihn im Simulator oder DeviceHub ins Querformat; simctl kann nicht falten oder drehen. Verwende Deep Links (HID-Taps erreichen möglicherweise nicht das innere Display), "locale": "relaunch" und "displaySize": "2853x2007".

Cross-Plattform-Apps (React Native, Flutter) können die Android-Aufnahme überspringen: Android-Tiles verwenden die iPhone- und iPad-Aufnahmen wieder, was die Standard-Geräte tun. Native Android-Apps nehmen ihre eigenen Bildschirme in sim-android/ auf, siehe Abschnitt 10.

5. Composition (Benutzer genehmigt vor jedem Rendern)

Skizziere jede Slide in ASCII: Überschrift, Geräteposition und -neigung, welches Element ausbricht und wo es landet. Hole eine Bestätigung ein, dann schreibe set.json.

 +------------------------------+
 |            WATER             |  Verb, eine Zeile
 |      EVERY PLANT RIGHT       |  Unterzeile, max 2 Zeilen
 |          ON TIME             |
 |      .--------------.        |
 |  [* 3 plants today]          |  Callout, angehoben, ragt links heraus
 |      |  Today ...   |        |  Gerät geneigt y 15, x 4
 +------------------------------+

6. Hintergrund (Background)

Ein Hintergrund pro Set, von jeder Sprache und jedem Gerät geteilt. Entweder CSS ("background": {"css": "radial-gradient(...), #1f4a37"}, das Demo verwendet dies) oder ein Bild ({"image": "assets/bg.png"}, Hintergrundgröße cover). Ein Bildgenerator eignet sich gut für eine weiche Platte; fordere ein nahtloses 9:16 Studio-Backdrop in der Markenfarbe mit weichem Licht an und gib explizit an: keine Objekte, kein Text, keine Geräte, keine Formen. Generiere zwei, der Benutzer wählt aus. Props (Sticker, Produktbilder) sind PNGs mit Alpha, die pro Slide platziert werden.

7. set.json und locales

Messe jedes Rechteck in Aufnahme-Pixeln mit measure.py, niemals nach Augenmaß:

$PY $S/measure.py sim/en-US/05-fill.png --at 700,790            # Füllt einen Button, Chip, Pill aus
$PY $S/measure.py sim/en-US/01-plan.png --ink 40,415,700,75     # Textbegrenzungen auf einer einfarbigen Fläche
$PY $S/measure.py sim/en-US/02-cook.png --grid 440,1510,340,110 # Zoom-Gitterbild im Temp-Verzeichnis
SchlüsselBedeutung
locales, devicesWas ein vollständiger Render abdeckt; Geräte-IDs aus $S/devices/devices.json
background{"image": ...} oder {"css": ...}, optional position
fonts{"family": "fonts/File.otf"}, Pfade relativ zum Projekt; Standard display ist die enthaltene Archivo Black
headlinefont, descFont, verbColor, descColor, shadow, verbTracking, descTracking, descWordSpacing
captureplatform, statusBarBand (Aufnahmezeilen, die weggeblendet werden, iOS-Standard [66, 128]), sets ({"tablet": {"dir": "sim-tablet", "statusBarBand": [12, 56]}}), devices ({"android-phone": "android"}, um ein Gerät auf ein anderes Aufnahmeset zu verweisen)
stylegloss, deviceShadow, thicknessRatio (Seitenwandtiefe), sideLayers
statusBartime, color der Statusleiste, die der Renderer zeichnet
layoutPro Geräte-ID, überschreibt das Layout der devices.json (deviceTop, deviceWidth, verbMax ...)
baseline{device: {locale: folder}} eines Live-Sets, für --compare
slidesListe, siehe unten

Slide: id, sim (Aufnahmedatei, falls nicht <id>.png), tilt {x, y, z} Grad, offset {x, y} Leinwand-Brüche, layout, breakouts, props (src, x, y, w Leinwand-Brüche, rotate, shadow, z: front oder back).

Breakout:

SchlüsselBedeutung
typecrop: die eigenen Pixel der Aufnahme; callout: vektorbasierte Tablette mit Locale-Text
rect oder anchor[x, y, w, h] in Aufnahme-Pixeln des Elements, von dem es stammt
at oder dx/dyZielposition (at = neue obere linke Ecke in Aufnahme-Pixeln) oder Versatz
scale, liftGröße und z-Höhe in Pixeln (Standard 80)
vacate, vacatePadFülle die ursprüngliche Stelle mit der umgebenden Farbe (verschoben, nicht kopiert)
radius, shadow, originEckradius in Aufnahme-Pixeln, Schattenstärke, Transformationsursprung
text, icon, styleCallout: Schlüssel im callouts-Objekt des Locales, tag oder sparkles, und font, size, bg, fg, padX, padY, gap, radius, weight, tracking, iconScale, iconColor

Jeder Wert innerhalb von slides kann pro Gerät und pro Sprache variieren: {"byDevice": {"phone": ..., "tablet": ..., "default": ...}} (Schlüssel: Geräte-ID, Aufnahmeset, default) und {"byLocale": {"de-DE": ..., "default": ...}}, beliebig verschachtelt. Rechtecke variieren fast immer pro Sprache, weil derselbe Chip auf Deutsch breiter ist.

Crops bleiben bis etwa 1,7x für große Elemente scharf. Kleine Chips und Texte werden zu Callouts, die vektorbasiert sind und in jeder Größe scharf bleiben.

Locales-Datei:

{
  "captures": "en-US",
  "dir": "ltr",
  "fonts": {"display": "fonts/NotoSansJP-Black.otf"},
  "slides": {
    "01-plan": {"verb": "Plan", "desc": "Your week in minutes", "callouts": {"savings": "approx. €7.81 saved"}}
  }
}

Nur slides ist erforderlich. captures veranlasst, dass ein Locale die Aufnahmen eines anderen Locales wiederverwendet (en-GB liest en-US). headline und statusBar überschreiben set.json. Archivo Black deckt nur Latein ab; Kyrillisch, Griechisch, CJK, Arabisch und Hebräisch benötigen einen fonts-Override, RTL benötigt "dir": "rtl".

8. Rendern (Render)

$PY $S/render.py <project>                                  # Alles
$PY $S/render.py <project> --locale de-DE --device iphone-67 --slide 01-plan
$PY $S/render.py <project> --compare                        # Baseline vs. neue Blätter

Überschriftsgrößen werden über alle Slides einer Sprache und eines Geräts geteilt, sodass ein Set wie aus einem Guss wirkt. Der Renderer stoppt, wenn das Seitenverhältnis einer Aufnahme nicht mit der Bildschirmöffnung des Geräts übereinstimmt.

9. Überprüfung (Review)

Öffne out/_sheets/<locale>-<device>.jpg und zoome in jedes Breakout. Als CHECK gedruckte Zeilen nennen das Problem (Überschrift bei Mindestgröße, Überlappung). Eine Überschrift bei Mindestgröße bedeutet, dass der Text zu lang ist: Kürze ihn, senke die Grenzen nicht. Zeige die Blätter dem Benutzer.

10. Weitere Sprachen und Geräte

Füge eine Sprache hinzu:

$PY $S/add_locale.py <project> es-ES init --from en-US     # Locale-Datei, byLocale-Platzhalter, Ordner
$PY $S/capture.py <project> run --locale es-ES             # Aufnahmen
#   Übersetze locales/es-ES.json: Store-Kopie, kurze Verben, Callouts passend zur Aufnahme
$PY $S/add_locale.py <project> es-ES measure --from en-US  # Finde Rechtecke neu, überprüfe das Side-by-Side-Bild
$PY $S/add_locale.py <project> es-ES measure --from en-US --write
$PY $S/add_locale.py <project> es-ES check                 # 0 Fehler vor dem Rendern
$PY $S/render.py <project> --locale es-ES

Eine regionale Variante (en-GB, de-AT, fr-CA): init --share-captures, dann ändern sich nur Texte.

Geräte in $S/devices/devices.json:

idLeinwandliestStore-Slot
iphone-671290x2796phone (1206x2622)ASC APP_IPHONE_67
android-phone1080x1920phonePlay Phone Screenshots
ipad-132064x2752tablet (2064x2752)ASC APP_IPAD_PRO_3GEN_129
android-tablet1792x2400tabletPlay 7" and 10" Tablet
iphone-duo2853x2007duo (2853x2007)ASC iPhone Duo

Die Rahmen sind generische Zeichnungen, die mit make_frame.py erstellt wurden, frei weiterverteilbar. Eine Aufnahmegröße ohne passenden Rahmen erhält einen:

# Native Android-Aufnahmen, 1080x2400, in sim-android/
$PY $S/make_frame.py --style android --screen 1080x2400 --device android-phone --captures android
# dann in set.json: "capture": {"sets": {"android": {"dir": "sim-android", "statusBarBand": [30, 105]}}}

Stile: ios, android, tablet, landscape. --canvas WxH setzt die Store-Größe für eine neue Geräte-ID. Miss statusBarBand bei einer echten Aufnahme: die Zeilen der Statusleiste plus etwas ...

Verwandte Skills