CommunityImagemgithub.com

meth0xy/store-screenshots

Gera conjuntos de capturas de tela para App Store e Google Play de ponta a ponta. Encontra os benefícios do aplicativo no código-fonte, captura telas reais de simuladores iOS e emuladores Android (iPhone, iPad, iPhone Duo, celular e tablet Android) em todos os idiomas, compõe cada slide em um canvas HTML com molduras de dispositivos, manchetes e destaques a partir de arquivos JSON de localidade, e renderiza cada localidade x dispositivo com Playwright. Use para criar um conjunto de capturas de tela da loja, adicionar um idioma, adicionar um tamanho de dispositivo ou recriar um conjunto onde o texto e a IU devem permanecer exatos.

O que é store-screenshots?

Este é um agente de IA especializado que automatiza todo o pipeline de criação de conjuntos de capturas de tela para lojas de aplicativos (iOS App Store e Google Play). Ele começa analisando o código-fonte do aplicativo para extrair os principais benefícios de venda e os mapeia para slides. Em seguida, captura telas reais de simuladores iOS e emuladores Android, compondo-as em um canvas HTML com molduras de dispositivos, manchetes e callouts vetoriais. Os textos são gerenciados via arquivos JSON de localidade, permitindo adicionar novos idiomas com pouquíssimo esforço. Tudo é determinístico: a mesma entrada gera exatamente os mesmos pixels, garantindo consistência e evitando retrabalhos manuais. Ferramentas auxiliares permitem medir precisamente as dimensões dos elementos na captura, ajustar layouts e validar a saída final.

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

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Você constrói conjuntos de capturas de tela como dados, não como imagens geradas. Cada slide é um canvas HTML com camadas: fundo, manchete, uma moldura de dispositivo segurando uma captura real e destaques (recortes da captura ou callouts vetoriais) que se destacam da tela em 3D. Cada texto está em locales/<locale>.json, então um novo idioma é um arquivo JSON mais as capturas, e a renderização é determinística: a mesma entrada gera os mesmos pixels.

$S abaixo é a pasta onde este SKILL.md reside, $PY é $S/.venv/bin/python. Se o venv não existir, crie-o uma vez:

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

Pipeline:

1 benefícios -> 2 slides -> 3 capture.json -> 4 captura (simuladores) -> 5 composição
-> 6 fundo -> 7 set.json + locales -> 8 renderizar -> 9 revisão -> (mais idiomas, dispositivos)

$S/../../examples/demo/ no repositório é um projeto completo (app fictício, dois idiomas, cinco dispositivos). Leia o set.json dele antes de escrever um.

Layout do projeto

<project>/
  capture.json                  app, dispositivos de captura, telas a capturar
  set.json                      composição compartilhada por cada localidade
  locales/<locale>.json         cada texto: verbo, subtítulo, textos de callout
  sim/<locale>/<slide>.png      capturas do celular (uma pasta por conjunto de captura)
  sim-tablet/  sim-duo/  sim-android/
  fonts/  assets/               fontes opcionais, imagem de fundo, adereços
  out/<locale>/<device>/        apenas arquivos da loja
  out/_sheets/                  folha de contato por localidade e dispositivo
  out/_captures/                folha de contato por localidade após capturar

Sugira store-screenshots/ na raiz do repositório do aplicativo. Adicione out/ e .cache/ ao .gitignore dele.


1. Benefícios

Leia o código-fonte: navegação (abas, rotas, telas), texto de integração, texto do paywall, README, listagem existente da loja. Liste as 5 a 8 coisas que um usuário obtém, classificadas por quanto elas influenciariam uma instalação. Um benefício por slide.

Cada manchete do slide é um verbo curto em maiúsculas mais um subtítulo de no máximo duas linhas: PLANEJE / SUA SEMANA EM MINUTOS, ECONOMIZE / EM CADA COMPRA. O verbo nomeia o benefício, não o recurso. Mostre a lista com a tela que comprova cada um e obtenha aprovação.

2. Slides

Id NN-nome; o número é a posição na loja. Escolha a tela por slide e observe o estado que ela precisa (logado, dados presentes, uma folha aberta). Incline telas com muitas imagens, mantenha telas densas de dados retas.

3. capture.json

Comece a partir de $S/templates/capture.json.

ChaveSignificado
app.iosbundleId, e app (caminho para um build .app do simulador) ou copyFrom (UDID de um simulador que o tenha instalado)
app.androidpackage, activity opcional, apk opcional para instalador
devices.<chave>platform ios ou android, dir (pasta de captura), iOS: name (simulador dedicado, criado pelo setup) e type (xcrun simctl list devicetypes), runtime opcional; Android: avd (emulator -list-avds)
extras do dispositivoappearance (light), locale (substitui o modo abaixo), displaySize (2853x2007 escolhe a tela interna do iPhone Duo), rotate (graus, para uma captura que sai de lado)
localepor plataforma. iOS reboot (padrão, mais confiável), relaunch (sem reinicializar, mantém a postura de um dobrável) ou launchArgs. Android app (padrão, idioma por app no Android 13+, precisa do localeConfig do app) ou system (precisa de uma imagem de emulador com root)
launchwait segundos após iniciar, url opcional para abrir em vez de iniciar (URL do cliente de desenvolvimento Expo), steps opcionais
screenslista de {id, steps, ready, after, devices, copyFrom}, além de blocos byDevice / byLocale mesclados sobre a tela

Os passos são executados em ordem e cada um espera (wait, padrão 1 a 2 s):

PassoEfeito
{"open": "myapp://route"}link profundo. Prefira isso a toques: funciona em todos os dispositivos e plataformas
{"tap": {"label": "Salvar"}}toca no elemento com esse rótulo de acessibilidade (ou {"id": ...}), correspondência exata depois substring
{"tap": {"at": [0.5, 0.9]}}toca em uma fração da tela
{"tap": {...}, "until": {"label": "Detalhes"}}toca novamente (até 3 vezes) até que esse elemento apareça; use para toques em telas que ainda estão estabilizando
{"waitFor": {"label": "Concluído", "timeout": 20}}espera até que um elemento esteja na tela, antes de toques em telas que carregam ou animam
{"type": "pasta"}, {"key": "enter"}, {"key": "back"}texto e teclas
{"swipe": [0.5, 0.8, 0.5, 0.3]}deslizar, frações
{"launch": true}reiniciar o aplicativo

ready: {"region": [x, y, w, h], "minStd": 20, "tries": 5, "delay": 3} refaz a captura enquanto essa região for uma cor sólida (linhas de esqueleto, um spinner, uma imagem ainda carregando). As capturas do iPhone são refeitas automaticamente quando o simulador incorpora a Dynamic Island nelas.

copyFrom: "01-home" reutiliza outra captura naquele dispositivo (um tablet mostrando duas telas em uma visualização dividida). devices: ["phone"] limita uma tela a alguns dispositivos.

capture.py PROJECT describe --device phone imprime elementos tocáveis com rótulos e molduras.

4. Captura

$PY $S/capture.py <project> doctor              # ferramentas, dispositivos, IDs de aplicativos
$PY $S/capture.py <project> setup               # criar/iniciar simuladores dedicados, iniciar AVDs, instalar o app
$PY $S/capture.py <project> run --locale pt-BR  # todos os dispositivos e telas
$PY $S/capture.py <project> run --locale pt-BR --device phone --screen 03-search
  • Os dispositivos de captura são dedicados: os simuladores iOS são criados por nome (Capture iPhone ...), o Android usa os AVDs nomeados em capture.json. Nunca aponte capture.json para o simulador em que o usuário trabalha e peça permissão antes de iniciar dispositivos ou alterar o idioma deles.
  • Após setup, o aplicativo geralmente precisa de um estado de demonstração: faça login em uma conta de demonstração, preencha dados, dispense diálogos da primeira execução (salvar senha, notificações, solicitações de avaliação). Faça isso uma vez por dispositivo; o estado sobrevive a mudanças de idioma. Peça ao usuário as credenciais de demonstração, nunca as escreva em capture.json.
  • Um build de desenvolvimento que mostra sobreposições de depuração (botões de menu de desenvolvimento, toasts) precisa ocultá-los para a sessão de captura. Remova-os localmente e não confirme a remoção.
  • Revise out/_captures/<locale>.jpg tile por tile: nenhum texto em outro idioma, nenhum diálogo, toast, spinner ou estado vazio. Corrija dados ou passos e execute novamente essa tela. O renderizador mostra a captura como está; nada pinta sobre um erro.
  • iPhone Duo: desdobre o simulador e coloque-o em paisagem no Simulador ou DeviceHub primeiro; o simctl não pode dobrar ou girar. Use links profundos (toques HID podem não alcançar a tela interna), "locale": "relaunch" e "displaySize": "2853x2007".

Aplicativos multiplataforma (React Native, Flutter) podem pular a captura Android: os tiles Android reutilizam as capturas do iPhone e iPad, que é o que os dispositivos padrão fazem. Aplicativos Android nativos capturam suas próprias telas em sim-android/, veja a seção 10.

5. Composição (usuário aprova antes de qualquer renderização)

Esboce cada slide em ASCII: manchete, posição e inclinação do dispositivo, qual elemento se destaca e onde ele pousa. Obtenha aprovação e então escreva set.json.

 +------------------------------+
 |            ÁGUA              |  verbo, uma linha
 |      CADA PLANTA NO           |  subtítulo, máximo 2 linhas
 |          TEMPO CERTO          |
 |      .--------------.        |
 |  [* 3 plantas hoje]          |  callout, elevado, saindo pela esquerda
 |      |  Hoje ...   |         |  dispositivo inclinado y 15, x 4
 +------------------------------+

6. Fundo

Um fundo por conjunto, compartilhado por todas as localidades e dispositivos. Ou CSS ("background": {"css": "radial-gradient(...), #1f4a37"}, a demonstração usa isso) ou uma imagem ({"image": "assets/bg.png"}, background-size cover). Um gerador de imagem funciona bem para um fundo suave; solicite um fundo de estúdio 9:16 sem costura na cor da marca com luz suave, e afirme explicitamente: sem objetos, sem texto, sem dispositivos, sem formas. Gere dois, o usuário escolhe. Adereços (adesivos, fotos de produtos) são PNGs com alfa colocados por slide.

7. set.json e locales

Meça cada retângulo em pixels de captura com measure.py, nunca a olho:

$PY $S/measure.py sim/pt-BR/05-fill.png --at 700,790            # preenche um botão, chip, pílula
$PY $S/measure.py sim/pt-BR/01-plan.png --ink 40,415,700,75     # limites de texto em uma área simples
$PY $S/measure.py sim/pt-BR/02-cook.png --grid 440,1510,340,110  # imagem de grade ampliada no diretório temporário
ChaveSignificado
locales, deviceso que uma renderização completa cobre; IDs de dispositivo de $S/devices/devices.json
background{"image": ...} ou {"css": ...}, position opcional
fonts{"family": "fonts/File.otf"}, caminhos relativos ao projeto; padrão display é o Archivo Black incluído
headlinefont, descFont, verbColor, descColor, shadow, verbTracking, descTracking, descWordSpacing
captureplatform, statusBarBand (linhas de captura mescladas, iOS padrão [66, 128]), sets ({"tablet": {"dir": "sim-tablet", "statusBarBand": [12, 56]}}), devices ({"android-phone": "android"} para apontar um dispositivo para outro conjunto de captura)
stylegloss, deviceShadow, thicknessRatio (profundidade da parede lateral), sideLayers
statusBartime, color da barra de status que o renderizador desenha
layoutpor ID de dispositivo, substitui o layout de devices.json (deviceTop, deviceWidth, verbMax ...)
baseline{device: {locale: folder}} de um conjunto ativo, para --compare
slideslista, abaixo

Slide: id, sim (arquivo de captura se não for <id>.png), tilt {x, y, z} graus, offset {x, y} frações do canvas, layout, breakouts, props (src, x, y, w frações do canvas, rotate, shadow, z: front ou back).

Breakout:

ChaveSignificado
typecrop: os próprios pixels da captura; callout: pílula vetorial com texto da localidade
rect ou anchor[x, y, w, h] em pixels da captura do elemento de onde vem
at ou dx/dyposição de pouso (at = novo canto superior esquerdo em pixels da captura) ou deslocamento
scale, lifttamanho e elevação z em pixels (padrão 80)
vacate, vacatePadpreencher o local original com a cor ao redor (movido, não copiado)
radius, shadow, originraio do canto em pixels da captura, intensidade da sombra, origem da transformação
text, icon, stylecallout: chave nos callouts da localidade, tag ou sparkles, e font, size, bg, fg, padX, padY, gap, radius, weight, tracking, iconScale, iconColor

Qualquer valor dentro de slides pode variar por dispositivo e por localidade: {"byDevice": {"phone": ..., "tablet": ..., "default": ...}} (chaves: ID do dispositivo, conjunto de captura, default) e {"byLocale": {"de-DE": ..., "default": ...}}, aninhados de qualquer forma. Os retângulos quase sempre variam por localidade, porque o mesmo chip é mais largo em alemão.

Os recortes permanecem nítidos até cerca de 1.7x para elementos grandes. Chips pequenos e texto tornam-se callouts, que são vetoriais e permanecem nítidos em qualquer escala.

Arquivo de localidade:

{
  "captures": "pt-BR",
  "dir": "ltr",
  "fonts": {"display": "fonts/NotoSansJP-Black.otf"},
  "slides": {
    "01-plan": {"verb": "Planeje", "desc": "Sua semana em minutos", "callouts": {"savings": "aprox. €7,81 economizados"}}
  }
}

Apenas slides é obrigatório. captures faz uma localidade reutilizar as capturas de outra localidade (en-GB lendo en-US). headline e statusBar substituem set.json. Archivo Black cobre apenas latim; Cirílico, Grego, CJK, Árabe e Hebraico precisam de uma substituição fonts, RTL precisa de "dir": "rtl".

8. Renderizar

$PY $S/render.py <project>                                  # tudo
$PY $S/render.py <project> --locale de-DE --device iphone-67 --slide 01-plan
$PY $S/render.py <project> --compare                        # folhas de linha de base vs novas

Os tamanhos das manchetes são compartilhados em todos os slides de uma localidade e dispositivo, para que um conjunto seja lido como um. O renderizador para quando a proporção de uma captura não corresponde à abertura da tela do dispositivo.

9. Revisão

Abra out/_sheets/<locale>-<device>.jpg e amplie em cada breakout. Linhas impressas como CHECK nomeiam o problema (manchete no tamanho mínimo, sobreposição). Uma manchete no tamanho mínimo significa que o texto é muito longo: encurte-o, não abaixe os limites. Mostre as folhas ao usuário.

10. Mais idiomas e dispositivos

Adicionar um idioma:

$PY $S/add_locale.py <project> es-ES init --from en-US     # arquivo de localidade, placeholders byLocale, pastas
$PY $S/capture.py <project> run --locale es-ES             # capturas
#   traduza locales/es-ES.json: texto da loja, verbos curtos, callouts correspondentes à captura
$PY $S/add_locale.py <project> es-ES measure --from en-US  # reencontra retângulos, revise a imagem lado a lado
$PY $S/add_locale.py <project> es-ES measure --from en-US --write
$PY $S/add_locale.py <project> es-ES check                 # 0 erros antes de renderizar
$PY $S/render.py <project> --locale es-ES

Uma variante regional (en-GB, de-AT, fr-CA): init --share-captures, então apenas os textos mudam.

Dispositivos em $S/devices/devices.json:

idcanvaslêslot da loja
iphone-671290x2796phone (1206x2622)ASC APP_IPHONE_67
android-phone1080x1920phoneCapturas de tela do Play
ipad-132064x2752tablet (2064x2752)ASC APP_IPAD_PRO_3GEN_129
android-tablet1792x2400tabletTablet de 7" e 10" do Play
iphone-duo2853x2007duo (2853x2007)ASC iPhone Duo

As molduras são desenhos genéricos feitos com make_frame.py, livres para redistribuir. Um tamanho de captura sem moldura correspondente ganha uma:

# capturas Android nativas, 1080x2400, em sim-android/
$PY $S/make_frame.py --style android --screen 1080x2400 --device android-phone --captures android
# então em set.json: "capture": {"sets": {"android": {"dir": "sim-android", "statusBarBand": [30, 105]}}}

Estilos: ios, android, tablet, landscape. --canvas WxH define o tamanho da loja para um novo ID de dispositivo. Meça statusBarBand em uma captura real: as linhas da barra de status mais algumas

... [truncado para tradução]

Habilidades Relacionadas