Comment créer des captures d'écran App Store pour une app React Native (2026)
Voilà ce que personne ne te dit quand tu soumets ta première app React Native sur l'App Store : il n'existe aucun moyen intégré de générer les captures d'écran demandées par le store. Les développeurs iOS natifs utilisent l'enregistreur de tests UI de Xcode ; les développeurs Android natifs ont Espresso intégré au build. React Native se superpose aux deux, avec ta logique applicative réelle qui tourne en JavaScript — et aucun de ces outils ne sait que ton JS existe. C'est à toi de faire le pont.
Cet article passe en revue les approches qui fonctionnent vraiment à l'ère de la New Architecture (RN 0.7x et supérieur, 2026), avec des commandes concrètes. Il est honnête sur les coûts, parce que chacune de ces options en a un réel. Puis il aborde ce qui vient après la capture — la composition marketing et la localisation — qui est un problème genuinement distinct quelle que soit la façon dont tu récupères les frames sources.
Le vrai problème : pas de pipeline intégré
App Store Connect veut des captures d'écran aux dimensions de pixels exactes, idéalement un ensemble par classe d'appareil et un ensemble par locale prise en charge. Google Play veut ses propres tailles. Un projet iOS natif peut piloter le simulateur via XCUITest et exporter des frames ; React Native techniquement aussi, mais le test que tu écris s'exécute contre le shell natif — le binaire compilé — pas directement contre tes composants JavaScript. Tu automatises une boîte noire qui se trouve à rendre ton JS.
Cette distinction a plus d'importance qu'il n'y paraît. Elle signifie que ton automatisation de captures d'écran peut casser pour des raisons qui n'ont rien à voir avec ton code React (un bundler Metro qui ne tourne pas, un simulateur bloqué sur une boîte de dialogue de permission, un build natif qui a divergé de ton JS) — et que la courbe d'apprentissage est celle de deux frameworks de tests natifs, pas de ton stack RN habituel. Il existe trois approches sérieuses. Choisis en fonction de ta fréquence de livraison.
Option 1 — fastlane snapshot (iOS) et screengrab (Android)
fastlane est le framework d'automatisation mobile open source de référence, et ses modules de capture d'écran sont l'option la plus éprouvée. Ils sont aussi les plus fastidieux à configurer pour React Native, car ils ont été conçus pour les projets natifs et ne font que tolérer RN.
iOS, via snapshot. Tu ajoutes une cible de test UI dans Xcode et tu écris des cas XCUITest en Swift qui pilotent l'app vers chaque écran à capturer. fastlane snapshot init dépose un Snapfile et un SnapshotHelper.swift dans ton dossier fastlane/. Dans ton test, tu appelles setupSnapshot(app), tu lances l'app, puis snapshot("01_home") à chaque état. Tu l'exécutes depuis le terminal avec fastlane snapshot — pas depuis Xcode, qui ne produira pas la bonne sortie. Il boucle sur chaque simulateur et locale définis dans ton Snapfile et écrit les PNG dans fastlane/screenshots/.
La subtilité React Native : snapshot lance l'app compilée, qui en mode debug a besoin que le bundler Metro tourne déjà. Ton Fastfile (ou un script wrapper) doit donc démarrer Metro en premier — l'astuce habituelle est de lancer npx react-native start dans une session tmux en arrière-plan avant d'appeler snapshot, puis de le stopper après. Les builds de release avec le bundle JS intégré évitent ça, mais nécessitent un build de release complet à chaque exécution.
Android, via screengrab. Framework entièrement différent : screengrab utilise Espresso. Tu ajoutes des appels Screengrab.screenshot("name") dans des tests instrumentés JUnit, tu déclares les permissions (DISABLE_KEYGUARD, WAKE_LOCK, CHANGE_CONFIGURATION, et les permissions de stockage), tu builds un APK de debug et un APK de test avec ./gradlew assembleDebug assembleAndroidTest, et tu exécutes fastlane screengrab. La sortie atterrit dans fastlane/metadata/android/. Comme pour iOS, Metro et l'émulateur doivent déjà tourner — screengrab ne les démarre pas pour toi.
Points forts :
- Intégré à CI et à l'abri des décalages. Connecte-le à ton pipeline et les captures d'écran se régénèrent à chaque build de release, toujours en phase avec l'app livrée.
- Vraie localisation par locale. Chaque locale s'exécute dans le simulateur/émulateur avec ses paramètres réels, donc les dates, chiffres et devises s'affichent nativement — pas simulés dans un outil de design.
- Gratuit, open source, mature. Pas d'abonnement, grande communauté, modes d'échec bien documentés.
Points faibles (sois honnête avec toi-même) :
- Tu maintiens deux suites de tests natifs. XCUITest en Swift pour iOS, Espresso/JUnit en Kotlin/Java pour Android — en tant que développeur RN, ce sont peut-être deux stacks que tu ne maîtrises pas.
- Les tests portent sur le shell natif, pas ta logique JS. Les tests portent sur les vues natives rendues ; ils n'ont pas connaissance de ton arbre de composants.
- La configuration prend un ou deux jours la première fois, et la danse avec le bundler Metro est une source récurrente de runs CI instables.
- La sortie est brute. Pas de légendes, pas de cadres d'appareils, pas de dégradés, pas de carrousel — juste l'interface brute de l'app à la résolution du simulateur.
- Mac obligatoire pour iOS. Le simulateur a besoin de Xcode.
Pour une comparaison approfondie sur la question de la composition, voir fastlane snapshot vs captures d'écran App Store sans code et la comparaison Mokbi vs fastlane.
Option 2 — Captures d'écran Detox (conçu pour React Native)
Detox est un framework de tests end-to-end de type boîte grise, conçu spécifiquement pour React Native par l'équipe de Wix. Si tu fais déjà tourner Detox pour tes tests e2e, les captures d'écran sont presque gratuites, et la courbe d'apprentissage est celle que tu voudrais maîtriser de toute façon — c'est une API JavaScript, pas du Swift ou du Kotlin.
L'appel de capture tient en une ligne dans n'importe quel test :
// full screen
const path = await device.takeScreenshot('01_home');
// a single element
await element(by.id('paywallRoot')).takeScreenshot('paywall');La conservation de ces images en tant qu'artefacts est contrôlée par le flag --take-screenshots (none, failing, manual, ou all) et configurée dans .detoxrc.js. En mode manual ou all, les tests réussis écrivent dans <artifacts-location>/✓ [test name]/[name].png. Tu pilotes l'app vers chaque état avec les mêmes matchers Detox que tu utiliserais pour des assertions, puis tu prends la capture.
Points forts :
- C'est une API JS. Tu écris les tests dans le même langage que ton app — pas de suite de tests native dans un autre langage à maintenir.
- Boîte grise, donc elle comprend RN. Detox se synchronise avec le bridge/JSI de l'app et attend qu'elle soit au repos, ce qui rend les captures d'écran bien moins instables que les attentes minutées à l'aveugle de XCUITest.
- Un seul framework, les deux plateformes. Le même fichier de tests capture iOS et Android.
- Tu l'as probablement déjà si tu fais des tests e2e, auquel cas le coût marginal des captures d'écran est minime.
Points faibles :
- Mettre Detox en place de zéro n'est pas trivial — configuration du build natif, un build de test dédié, et configuration de l'émulateur/simulateur. Si tu ne le fais pas déjà tourner, c'est un vrai investissement.
- La gestion des locales est à ta charge. Detox ne balaie pas automatiquement toutes les locales App Store comme le fait le Snapfile de
snapshot; tu scriptes les changements de locale ou relances avec des paramètres différents. - La sortie est toujours brute. Comme fastlane — interface brute de l'app, pas de couche marketing.
- Les captures d'écran peuvent différer selon les machines hôtes (un problème connu de Detox), ce qui compte si tu les compares en CI mais est sans conséquence pour les assets du store.
Option 3 — Capture manuelle (la plus simple, et sous-estimée)
Ouvre le simulateur iOS ou un émulateur Android, navigue manuellement dans ton app jusqu'à chaque écran, et capture la frame. Sur iOS, Cmd-S dans le simulateur enregistre un PNG correctement dimensionné sur le bureau ; xcrun simctl io booted screenshot home.png fait la même chose depuis le terminal et est facile à scripter légèrement. Sur Android, le bouton appareil photo de l'émulateur ou adb exec-out screencap -p > home.png capture l'écran. Un appareil physique fonctionne aussi — capture, puis transfère les fichiers via AirDrop ou un autre moyen.
Cette option est trop vite écartée. Elle ne nécessite aucune configuration, ne casse jamais en CI puisqu'il n'y a pas de CI, et pour une app qui livre quelques fois par an c'est franchement le chemin le plus rapide vers un ensemble de frames sources. L'inconvénient est évident et réel : c'est manuel, donc ça ne se régénère pas tout seul, et si tu modifies un écran tes captures deviennent obsolètes jusqu'à ce que tu les refasses. Pour un carrousel de cinq panneaux, c'est dix minutes de travail par release — moins cher que de maintenir une automatisation de tests qu'on fait tourner deux fois par an.
Ce que tout le monde oublie : la composition et la localisation
Voici ce qui unit les trois options : chacune produit des captures d'écran brutes de l'app, et des captures d'écran brutes ne sont pas ce qui convertit sur le store. Le carrousel App Store qui fait vraiment bouger les installations a un cadre d'appareil autour de l'écran, une légende d'une ligne au-dessus qui explique le bénéfice, un fond qui n'est pas le blanc de ton app, et une continuité sur les cinq panneaux. Aucun des outils de capture ci-dessus ne produit quoi que ce soit de tout cela — ils s'arrêtent à la frame brute. Ce n'est pas un défaut en eux ; c'est simplement un travail différent.
C'est là que Mokbi s'insère, et il vaut la peine d'être précis sur la frontière : il ne capture pas tes captures d'écran sources — c'est le rôle du simulateur, de l'appareil, ou de fastlane/Detox ci-dessus. Ce qu'il fait, c'est la couche de composition marketing et de localisation qui vient ensuite. Tu déposes tes frames brutes dans un éditeur navigateur, tu les enveloppes dans de vrais cadres d'appareils, tu ajoutes des légendes, tu construis des carrousels multi-panneaux, puis en un clic tu traduis les légendes en 50 langues et tu exportes en lot à toutes les dimensions du store. La conception est gratuite avec un aperçu en filigrane ; l'export et la publication illimités sont inclus dans un abonnement — Solo €29.99/mo (1 app) ou Studio €49.99/mo (jusqu'à 5 apps), sans achat unique. La raison pour laquelle il s'intègre naturellement, c'est qu'il résout le problème que ton pipeline de capture ne tente même pas : transformer un dossier de PNG en carrousel localisé et prêt pour le store sans ouvrir Photoshop ni redimensionner à la main pour 50 langues.
Le workflow combiné réaliste
- Capture les frames sources. Choisis une option : fastlane (snapshot + screengrab) en CI pour les releases fréquentes, Detox si tu fais déjà des tests e2e, ou capture manuelle dans le simulateur pour les releases peu fréquentes. Résultat : un dossier de PNG bruts par écran, par appareil.
- Compose, légende et encadre. Dépose les frames brutes dans un éditeur navigateur. Ajoute des cadres d'appareils, écris les légendes de bénéfice, construis le carrousel en cinq panneaux, choisis un fond.
- Traduis. Traduis les légendes en lot dans les 50 langues en un clic, puis vérifie à la main les langues qui comptent le plus pour toi.
- Exporte en lot. Exporte chaque locale à chaque dimension requise pour App Store Connect et Google Play en une seule passe.
- Échange à la prochaine release. Recapture les frames modifiées (relance fastlane/Detox, ou capture-les à la main), rouvre le projet sauvegardé, échange les captures d'écran, réexporte. Le travail de légendes et de traduction est déjà fait.
Quand tu peux passer l'automatisation
Si tu livres une à trois releases par an — ce qui décrit la plupart des apps React Native indépendantes — le coût de configuration de fastlane ou Detox ne se rentabilise presque jamais. Tu passerais une journée à câbler XCUITest et la danse avec le bundler Metro pour économiser dix minutes de capture manuelle deux fois par an. Le calcul ne tient pas. Capture à la main depuis le simulateur, compose et localise dans le navigateur, et tu as fini en moins de temps total que la configuration de l'automatisation n'en aurait pris.
L'automatisation mérite sa place quand tu livres chaque semaine ou chaque jour, quand le décalage des captures d'écran devient un bug récurrent, ou quand tu gères un portefeuille d'apps et que le coût de capture par app se multiplie. À cette échelle, fastlane en CI (ou Detox s'il est déjà dans ton stack) est le bon choix pour l'étape de capture — et tu l'associes quand même à un outil de composition dans le navigateur pour la couche marketing, parce qu'aucun pipeline de capture ne produit un carrousel fini.
Avant d'exporter quoi que ce soit, ça vaut la peine de vérifier les cibles : les tailles de captures d'écran App Store que tu dois vraiment uploader, et les exigences de captures d'écran App Store qui font rejeter les soumissions. Les avoir en tête dès le départ évite un aller-retour avec App Review.