Automate Screenshot Framing with Text Using Fastlane

Framing your App Store screenshots greatly improves your store listing. But doing it manually takes hours away from perfecting your app. Instead, here's how you automate the process of adding device frames and text to your screenshots.

Written by 

In my last post, I shared how to generate localized screenshots of an app through the use of UI testing and Fastlane. Let's get our screenshots ready for the App Store with this step-by-step guide on how you add device frames, localized text and a background to each of them - everything automated with Fastlane frameit.

I hope you're ready to not ever using Photoshop to frame your screenshots again? This might get you extremely productive - proceed with caution!

Initializing Fastlane frameit

The first thing you need to do is to install Fastlane if you haven't already. Open your terminal and run this command: sudo gem install fastlane -NV.

We'll be working with frameit which depends on ImageMagick, so we need that as well: brew install imagemagick.

Framing screenshots

When you generate your screenshots using Fastlane, as demonstrated in the last post, you end up with a folder called "screenshots" containing subfolders with screenshots inside for all the languages that you support. It looks like this:

That is our starting point. To add frames to your screenshots, open the terminal, navigate to the directory containing the screenshots and run fastlane frameit. You can also add silver frames instead of space gray frames by running fastlane frameit silver.

What happens is that frameit looks for screenshots inside the directory with names matching its supported devices. It then creates framed versions of those screenshots.

Now, that's how you add frames to your screenshots. Let's build on this by adding text and a background to our screenshots.

Text and background

We can easily add a background and text below or above the framed screenshots in fonts and colors that we define. The magic behind this all starts in a Framefile.json where we define general and screenshot specific information. Create this at the top of the "screenshots" folder. It could look like this:

  "default": {
    "keyword": {
      "fonts": [
          "font": "./fonts/BebasNeue-Regular.ttf",
          "supported": ["en-US"]
    "color": "#000000"
    "title": {
      "fonts": [
          "font": "./fonts/BebasNeue-Regular.ttf",
          "supported": ["en-US"]
      "color": "#FFFFFF"
    "background": "./background.jpg",
    "padding": 50
  "data": [
      "filter": "AllCards"
      "filter": "CreateCard"
      "filter": "Presentation"
      "filter": "DarkMode"

In here, we define colors and fonts for text in our screenshots, more specifically keywords and titles. We also provide a path to a background image to be used. The data key contains screenshot specific properties which is related to keywords and titles.

The result of this is a screenshot that looks like this:

Here, we see that the keyword is "CUE CARDS" and the title is "PREPARE THEM ON THE GO" using our defined font and colors. We also see that a nice blue background image was added.

Keywords and titles

Adding keywords and titles to screenshots is done using the data key that specifies screenshot specific properties. The filter property inside of data is used to link keywords and titles with screenshots. An example from Fastlane docs:

If a screenshot is named iPhone 8-Brainstorming.png you can use value Brainstorming for filter. If there are more than one filter matching an entry, they will all be applied in order (which means that the last one has the highest precedence). All other keys from that array element will only be applied on this specific screenshot.

So basically, provide a filter property for every screenshot of your app (disregarding all variations of different screen sizes and languages). Now you just need to provide the specific text strings to be used. Inside each of the different languages subfolders, we create a keyword.strings and title.strings file with text specific to the language and screenshot.

Here's an example of the keyword.strings file:

"AllCards" = "CUE CARDS";

"CreateCard" = "FAST AND EASY";

"Presentation" = "PRESENT IT";

"DarkMode" = "DARK MODE";

The title.strings could look like this:

"AllCards" = "Prepare Them On The Go";

"CreateCard" = "Think Content, Not Layout";

"Presentation" = "With Timer To Guide You";

"DarkMode" = "Choose Your Preference";

This is all there is to keywords and titles. That leaves us with a file structure looking like this:

Go ahead and run fastlane frameit at the top of the directory containing the screenshots. This time, frameit will look at the screenshot information we provided in Framefile.json and generate nicely looking framed screenshots ready for the App Store.

Optional: iPad Pro (12.9-inch) (3rd generation) support

Fastlane is currently missing support for iPad Pro (12.9-inch) 3rd gen. If you plan on using that, I suggest that you take a look at this GitHub issue. As a workaround right now, you can manually add support by running:

// fetch missing device frames
curl -o ~/.fastlane/frameit/latest/Apple\ iPad\ Pro\ \(12.9-inch\)\ \(3rd\ generation\)\ Space\ Gray.png
curl -o ~/.fastlane/frameit/latest/Apple\ iPad\ Pro\ \(12.9-inch\)\ \(3rd\ generation\)\ Silver.png

// update device offset
sed -i '' -e '$ d' ~/.fastlane/frameit/latest/offsets.json
sed -i '' -e '$ d' ~/.fastlane/frameit/latest/offsets.json
cat >> ~/.fastlane/frameit/latest/offsets.json <<EOL
      "iPad Pro (12.9-inch) (3rd generation)": {
      "offset": "+200+200",
      "width": 2048


That's it! Fastlane frameit will save you a lot of time after you finish the setup. A complete example of generating screenshots and framing them can be found in the source code for my app called QCards on GitHub.

Stay tuned for future posts like this one about automating your workflow!

Share this post


You may also like


How Do I Work?

Over the past few years, I’ve been exposed to various ideas and processes that have affected my way of working in software development teams. From my experiences, here’s what has helped me work as efficiently as possible as a software developer.


Manage Your iOS Resources Type-Safely with R.swift

A common frustration with the iOS platform is that resources are accessed using magic strings. In practice, this means you’ll find out if an image, icon, localized string etc. exists at runtime. Either by seeing what you were hoping for or getting a hard crash. Let’s fix this by introducing your new best friend – R.swift.