Automate Flutter App Store screenshots with GitHub Actions
Step-by-step: wire screenstack_sdk into a Flutter project, declare your screens in screenstack.yml, and ship App Store + Play Store screenshots from CI on every push.
Flutter teams have a screenshot problem. The simulator changes, you tap through five screens, ⌘⇧4 each one, then open Figma to crop it into the iPhone 16 Pro Max slot, the 6.7″ slot, the iPad Pro slot, and the Play Store. By the time you're done it's an afternoon. The next release, it's an afternoon again.
This guide wires screenstack_sdk into a Flutter project so GitHub Actions
handles all of that on every push. The total setup is about 30 minutes and it pays
back the moment your UI changes.
What you need before you start
- A Flutter project on 3.16 or later.
- An integration_test setup. If you don't have one yet, it's literally
flutter pub add --dev integration_test+ a one-file harness. - A free ScreenStack account and a project ID.
Step 1 — add the package
Add screenstack_sdk to your dev dependencies:
# pubspec.yaml
dev_dependencies:
screenstack_sdk: ^3.1.0
integration_test:
sdk: flutter Then run flutter pub get. The SDK piggybacks on your existing
integration tests; it doesn't introduce a new test runtime.
Step 2 — declare your screens
Create a screenstack.yml at the repo root. This is the only configuration
file you'll write — it describes the screens you want captured and the device sizes
you want them composited into.
project: prj_abc123 # from your /app project list
deviceProfile: iphone-15-pro-max
testUser:
secretRef: ssr_xxx # encrypted in ScreenStack
screens:
- route: /home
targets: ["iOS App Store/Home", "Google Play/Home"]
- route: /pricing
targets: ["iOS App Store/Pricing"]
- route: /settings
targets: ["iOS App Store/Settings", "Google Play/Settings"] The secretRef points at credentials stored encrypted in your ScreenStack
project. They're fetched at run time by the SDK using a short-lived bearer token —
nothing sensitive ever lives in this file or your build logs.
Step 3 — the GitHub Actions workflow
One workflow file. The SDK does the rest:
# .github/workflows/screenshots.yml
name: ScreenStack
on:
push:
branches: [main]
workflow_dispatch:
jobs:
screenshots:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.x'
- run: flutter pub get
- run: flutter test integration_test/
env:
SCREENSTACK_TOKEN: ${{ secrets.SCREENSTACK_TOKEN }} The token comes from the /app/settings page after you authenticate. It's scoped to a single project and you can rotate it any time.
Step 4 — compose backdrops + captions in the editor
By default ScreenStack composites your captures inside the device frame you declared
( iphone-15-pro-max in the YAML above ) on a plain backdrop. To add brand
gradient backdrops and captions, open the editor at /app/project/{projectId}/editor, drop the captured screenshot into a
canvas, and pick from the gradient presets. The composition saves automatically; the
next CI run re-uses it.
Captions are rendered at composite time, so changing the caption text doesn't require re-capturing — it just re-exports. Useful when you want A/B-test variants or seasonal messaging.
Step 5 — pipe to App Store Connect with fastlane deliver
ScreenStack exports PNGs at the exact dimensions App Store Connect requires (1320×2868
for iPhone 16 Pro Max, 1290×2796 for the 6.7″ slot, 2048×2732 for iPad Pro 12.9″, etc).
The simplest upload path is still fastlane deliver:
fastlane deliver \
--screenshots_path ./screenshots \
--skip_metadata true \
--skip_binary_upload true Add a final step to your workflow that downloads the ScreenStack artifact and runs deliver against it. Or do the same with Google Play's API for Play Console uploads.
What you get
Every push to main, the workflow runs your integration tests, the SDK
captures each declared screen, and ScreenStack composites them at every store-required
size. Your /screenshots directory shows up as a build artifact you can
download or pipe straight to App Store Connect.
Total moving parts: one YAML, one workflow, one editor canvas. Total maintenance:
zero, until you ship a new screen. Then you add one line to screenstack.yml and the next CI run handles it.
See also
- /for/flutter — the full Flutter landing page
- /screenshot-sizes — every Apple + Google size in 2026
- /alternatives/fastlane-snapshot — when to use which
Ready to wire this up?
Free tier includes the SDK, the editor, and 5 exports a month. Pricing is on /pricing.