Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Screenshots as code: shipping Play Store assets...

Screenshots as code: shipping Play Store assets from a unit test

Updating Play Store screenshots usually goes like this: someone takes captures on a device, a designer puts them into frames, someone else translates the headlines, and the whole thing goes out of date at the next redesign. At Aircall we replaced that process with a JVM unit test.

This talk covers a small tool module that renders our real Compose screens from the same fixtures as their Android Studio previews. It runs headlessly with Robolectric and Roborazzi, so there’s no emulator, no device and no golden images. Each screen goes into a real Pixel device frame on a mesh gradient background with a localized headline, and the output is Play-compliant PNGs for every screen and locale. A manual CI job then uploads them through the Play Developer API as a single atomic edit.

You’ll leave with a pattern you can reuse to treat store assets like any other build output: reviewable, reproducible and one click away from the store.

Julien Salvi

November 12, 2026

Transcript

23 slides
  1. Modena Screenshots as code: shipping Play Store assets from a

    unit test Julien Salvi Android @ Aircall
  2. Building and pushing new screenshots to the store might be

    quite time consuming and involve many teams. And having them up-to-date… 🙈 Question: how many time a year you update your store assets? Are they up-to-date?
  3. The whole pipeline • • • • Code: @Preview fixtures

    + copy + device art Generator: Robolectric + Roborazzi, headless CI generates and uploads 15 PNGs as store artifacts /prepare-release tells us when to regenerate
  4. The Previews It starts from the code • Real screen

    Composable from production • Same fixtures as the Android Studio @Preview
  5. The Refactors The little bumps along the way • •

    • We refactored InCallScreen, MessageComposer, ConversationDetailHeader Composables took plain params but resolved a Hilt ViewModel inside (getViewModel<_, XFactory>) Remember to check your Composable
  6. The Combination Two passes and a real Pixel frame •

    A real back.webp image to render Pixel 10 Pro device • Draw screenshot first, frame on top • Clip the screenshot to a rounded rect • Fake status bar drawn with plain Canvas
  7. The Marketed Look Localized headlines, per-screen look • Android resources,

    5 locales ( • In-screen fake data are localized too • Each screen has its own frame style • , , , , ) A frame style is a Painter: base horizontal gradient + soft glow
  8. The CI Jobs Two manual jobs • store-screenshots-generate: cheap, safe

    to re-run, artifact generation • store-screenshots-upload: replaces the live listing for every locale
  9. The Play Store Update One atomic Play edit • Validate

    all 5 locales are complete before any network call • Upload order = display order • Same Play Developer API access as the release upload, no new integration
  10. The Release Staying fresh • Our skill /prepare-release runs a

    screenshots audit • git diff since the last tag on the 3 screens, fixtures, copy, frame and spec • Changed? The release MR gets updated with a warning
  11. Key takeaways • 📸 Treat store assets like any other

    build output. • 📱Render the real screens from shared fixtures. • 🏗 Screen refactoring can be needed • 🛞 Screenshot code can drift and requires maintenance • 👉 Human is the gatekeeper of the final click

More Decks by Julien Salvi

Other Decks in Programming