Files
Every key of the files the tool keeps in your app, with what it does, from the schema itself.
The tool keeps an app's setup in three kinds of file. Each has a JSON Schema in schema/,
so an editor checks and completes it as you type.
store-shots.config.json
| Key | Type | What it is |
|---|---|---|
projectName | text | The app's name in the editors and in contact sheets. |
bundleId | text, optional | The iOS bundle id, for App Store Connect. |
defaultLocale | text | The language other languages start from, and whose copy and captures fill gaps. |
locales | list of text | Every App Store language the app's screenshots and listing are made in (e.g. en-US, de-DE). |
paths | object | Where the tool reads and writes, relative to the app; the defaults suit nearly every app. |
paths.manifest | text | The screens and pages. Default: "store/manifest.json". |
paths.content | text | The copy, one file per language. Default: "store/content". |
paths.raw | text | The captures, by device family and language. Default: "store/raw". |
paths.assets | text | Fonts, logos, backgrounds and layer art. Default: "store/assets". |
paths.outputScreenshots | text | Where the App Store screenshots go, for fastlane deliver. Default: "fastlane/screenshots". |
paths.outputPlay | text | Google Play (supply) metadata root; screenshots go under <locale>/images/phoneScreenshots/. Default: "fastlane/metadata/android". |
paths.metadata | text | The store text, one folder per language, for fastlane deliver. Default: "fastlane/metadata". |
paths.generated | text | Pages, iPhone Duo, header and search images, events, contact sheets; not committed. Default: "store/generated". |
paths.previews | text | App Preview videos, <previews>/<locale>/*.mp4|m4v|mov; readiness checks them and asc push default uploads them. Default: "store/previews". |
targets | list of enum | The devices to render for, by id (iphone-6.9-1320x2868, header-3840x1646, ...). |
sourceDevices | map of text | target id -> raw capture device folder name under paths.raw |
brand | object | The app's look: fonts, colours and the default background. A theme sets these. |
brand.font | object | The body font. |
brand.font.family | text | The font family, as Google Fonts names it, or a family added locally. Default: "Inter". |
brand.font.source | "google" or "local" | Where store-shots fonts add gets it from. Default: "google". |
brand.font.weights | list of whole number | The weights downloaded; headlines use the heaviest a headline font lists. Default: [400, 600, 700]. |
brand.font.fallbacks | list of text | Extra families tried after family, in order (must be local: fonts add). Bundled fallbacks are appended automatically. Default: []. |
brand.headlineFont | object, optional | Optional display face for headlines (e.g. a serif); body copy keeps font. |
brand.headlineFont.family | text | The font family, as Google Fonts names it, or a family added locally. Default: "Inter". |
brand.headlineFont.source | "google" or "local" | Where store-shots fonts add gets it from. Default: "google". |
brand.headlineFont.weights | list of whole number | The weights downloaded; headlines use the heaviest a headline font lists. Default: [400, 600, 700]. |
brand.headlineFont.fallbacks | list of text | Extra families tried after family, in order (must be local: fonts add). Bundled fallbacks are appended automatically. Default: []. |
brand.background | object, optional | Project-wide default background; screens inherit it unless they override (backgroundImage "none" opts out of a texture). |
brand.background.background | text, optional | Any CSS background: a colour, a gradient, several layered. |
brand.background.backgroundImage | text, optional | Over the background: "asset:<file in store/assets>", "pattern:<waves, dots, grid, lines, zigzag, rings, crosses, checker or noise>", or "none". |
brand.background.patternColor | text, optional | Line colour of a pattern (any CSS colour; noise ignores it). |
brand.background.patternScale | number, optional | Size of a pattern's tiles, 0.25 to 4 times the default. |
brand.background.span | true or false, optional | Stretch the project-default background across the whole screenshot strip (each screen shows its slice). |
brand.primary | text | The brand colour: the default background, and Full Bleed Card's card. Default: "#111111". |
brand.onPrimary | text | The text colour on primary. Default: "#FFFFFF". |
brand.accent | text, optional | Colour for the eyebrow and caption (a sub-line in a second colour); default: the text colour. |
output | object | How the files are written. |
output.format | "png" | The file format; PNG only for now. Default: "png". |
output.backgroundColor | text | The colour transparency is flattened onto, since the stores refuse alpha. Default: "#FFFFFF". |
output.cleanBeforeRender | true or false | A full run deletes the files of the last run that are no longer planned. Default: true. |
validation | object | How strict the checks are. |
validation.strictTranslations | true or false | A missing translation is an error (true) or a warning (false). Default: true. |
validation.failOnOverflow | true or false | Text that overflows at its smallest allowed size is an error (true) or a warning. Default: true. |
validation.failOnAlpha | true or false | A rendered file with transparency is an error (true) or a warning. Default: true. |
validation.failOnTextOverlap | true or false | Text overlapping the device shell is a warning by default (designers do it on purpose); true makes it an error. Default: false. |
validation.screensPerTarget | object | How many screenshots each device and language should have (Apple takes 1 to 10). |
validation.screensPerTarget.min | whole number | Fewer is reported. Default: 3. |
validation.screensPerTarget.max | whole number | More is reported. Default: 10. |
metadata | object | The store text in fastlane/metadata. |
metadata.manage | true or false | The tool edits and checks the store text; false leaves it to you. Default: true. |
metadata.fields | list of enum | The fields Listing shows and readiness requires. Default: [...METADATA_FIELDS]. |
presets | map of map of any | Named override presets applied to screens from the editor ("apply preset"). |
capture | object | Automated capture: how to put the simulator into a known state (plan section 7.5). |
capture.state | map of any | AsyncStorage entries written into the simulator's app container before each capture run, so screens never show an empty streak or onboarding. Values are stored as JSON; strings are written through unchanged. \{today\} and \{today-N\} in any string resolve to YYYY-MM-DD at run time, which keeps a seeded streak from going stale between runs. |
capture.storageDir | text | Folder under Library/Application Support/<bundleId> that holds AsyncStorage. Default: "RCTAsyncLocalStorage_V1". |
capture.appleLanguages | map of text | App Store locale -> iOS AppleLanguages value, when the two differ. |
capture.settleSeconds | number | Seconds to wait after opening a deep link before the screenshot. Default: 2. |
capture.languageSettleSeconds | number | Seconds to wait for SpringBoard after switching the simulator language. Default: 8. |
scenes | object, optional | The art pipeline behind store/assets: Blender renders and their post-processing, in order. |
scenes.blender | text, optional | Path to the Blender binary (default: $BLENDER, /Applications/Blender.app, or blender on PATH). |
scenes.steps | list of object | The steps, in order. |
scenes.steps[].id | text | The step's name, for scenes render \<step\> and needs. |
scenes.steps[].blender | text, optional | Run as blender -b --factory-startup with this script; its arguments follow --. |
scenes.steps[].python | text, optional | Run with python3 -I; its arguments are the usual sys.argv[1:]. |
scenes.steps[].args | list of text | \{root\}, \{work\} and \{assets\} are replaced with absolute paths. Default: []. |
scenes.steps[].inputs | list of text | Files or folders that re-run the step when they change (the script's folder always does). Default: []. |
scenes.steps[].outputs | list of text | Files the step writes; a missing one re-runs it. Default: []. |
scenes.steps[].needs | list of text, optional | Earlier steps whose output it reads: when one runs, so does this. Default: every earlier step. |
fastlane | object | The app's own fastlane lanes the tool may run. It never runs one that builds or submits. |
fastlane.enabled | true or false | False turns off the lanes and the credentials check. Default: true. |
fastlane.lanes | object | The lane names, as \<platform\> \<lane\>. |
fastlane.lanes.validate | text | Checks the store text against the limits. Default: "ios validate_metadata". |
fastlane.lanes.metadata | text | Uploads the store text. Default: "ios metadata". |
fastlane.lanes.screenshots | text | Uploads the screenshots. Default: "ios screenshots". |
store/manifest.json
The screens, in order, and the named pages.
screens[]
| Key | Type | What it is |
|---|---|---|
id | text | The screen's name: lowercase letters, digits and dashes. It names its copy, captures and files. |
order | whole number | Its position on the default page, from 1. |
enabled | true or false | On the default page; false keeps it for other pages, or for the header and event pictures. Default: true. |
template | text | The template id: hero-top, split-caption, full-bleed-card or feature-graphic. |
source | object | Where the screen's capture is. |
source.filePattern | text | Interpolates {order} {id} {locale} {device} {target}. Relative to raw/<device>/<locale>/. Default: "{order}-{id}.png". |
source.localized | true or false | false: use the default-locale capture for every locale. Default: true. |
source.deepLink | text, optional | Deep link the capture helper opens before screenshotting (capture --all), e.g. "braele://session/478". |
targets | list of text, optional | Only for targets listed here; default: all configured targets. |
panorama | object, optional | Panorama: render one artwork slices screenshots wide and cut it into consecutive files (order, order+1, ...). The following order numbers are reserved for the slices. |
panorama.slices | whole number | How many screenshots wide: 2 or 3. |
overrides | map of any | The layout and background the inspector sets; see screens[].overrides below. |
layers | list of object (by "type") | Extra image/text elements composited over the template. Text layers read content field <layer id>. |
appearance | "light" or "dark", optional | What the capture shows. Apple suggests one Dark Mode screenshot when the app supports it; readiness looks for it. |
screens[].overrides
What the inspector's Layout and Background tabs set. Every template takes these; Full Bleed Card
adds cardPosition and cardColor.
| Key | Type | What it is |
|---|---|---|
background | text, optional | CSS background colour/gradient; default derives from brand.primary. |
backgroundImage | text, optional | Background image layered over background: "asset:<path under store/assets>" (e.g. "asset:backgrounds/waves.png", cover-fitted) or a built-in pattern: "pattern:waves" | "pattern:dots" | "pattern:grid". |
patternColor | text, optional | Line colour for built-in patterns (any CSS colour; ignored by "noise"). |
patternScale | number, optional | Tile size multiplier for built-in patterns. |
screenshotScale | number, optional | Device width as a fraction of the canvas width. |
screenshotOffsetX | number, optional | Horizontal nudge of the device, fraction of the target width (negative = towards the start side). Panoramas may go up to +-3. |
screenshotOffsetY | number, optional | Vertical nudge of the device, fraction of canvas width (positive = down). |
deviceTilt | number, optional | Rotation in degrees. |
textWidth | number, optional | Text column width as a fraction of the usable width (1 = full width). |
textSide | "start" or "end", optional | Which side the text column hugs when narrower than full width (logical: start = left in LTR). |
textOffsetX | number, optional | Horizontal nudge of the text block, fraction of the target width (mirrored in RTL). |
textOffsetY | number, optional | Vertical nudge of the text block, fraction of canvas width (positive = down). |
textOffsetX2 | number, optional | Slide 2's text, across (a wide screen's slides each have their own). |
textOffsetY2 | number, optional | Slide 2's text, down. |
textOffsetX3 | number, optional | Slide 3's text, across. |
textOffsetY3 | number, optional | Slide 3's text, down. |
textAlign | "start" or "center" or "end", optional | Text alignment (start = left in left-to-right languages). |
textColor | text, optional | Text colour override (any CSS colour); default brand.onPrimary. |
accentColor | text, optional | Eyebrow and caption colour (any CSS colour); default brand.accent, else the text colour. |
shell | "dark" or "light" or "none" or text or map of "dark" or "light" or "none" or text, optional | Neutral shell ("dark" | "light" | "none") or an official device frame: "frame:<name>" (see store-shots frames list). Either one value for every target, or a map keyed by target family ({ "iphone": ..., "ipad": ... }) when the same screen needs a different frame per device. |
screens[].layers[]
A layer is an image (type: "image") or a line of text (type: "text"): image and text share id,
x, y, width, rotate, opacity and targets.
sets[]
| Key | Type | What it is |
|---|---|---|
id | text | The page's name in the tool: lowercase letters, digits and dashes. |
kind | "custom" or "ppo" | "custom" for a custom product page, "ppo" for an optimization test treatment. |
name | text, optional | The page's or treatment's name in App Store Connect, for your reference. |
screens | list of text | Screen ids, in the order the set shows them. |
deepLink | text, optional | Custom product pages: where the app opens when installed from this page (a URL or the app's own scheme). |
appIconName | text, optional | Optimization treatments: an alternate app icon in the shipped binary (its name in the asset catalog). |
experiment | text, optional | Optimization treatments: the experiment (test) it belongs to; treatments with one name share it. |
ascId | text, optional | App Store Connect's id for this page or treatment, written when the tool first uploads it. An editor sends "" to unlink it (the page was deleted there, or the test ended). |
store/content/<locale>.json
| Key | Type | What it is |
|---|---|---|
locale | text | The language this file is for, as in the file name. |
direction | "ltr" or "rtl", optional | Right to left mirrors the layouts; default: from the language. |
screens | map of map of text or null | screen id -> field -> text (null = intentionally empty) |
sets | map of object, optional | set id -> that page's or treatment's own text in this locale. |
sets.<page>
| Key | Type | What it is |
|---|---|---|
promotionalText | text, optional | Shown above the description on this page (custom product pages; 170 characters). |
keywords | list of text, optional | Keywords from the app's keyword field that lead search to this page (custom product pages). |
screens | map of map of text or null | screen id -> field -> text, over the default page's copy for that screen. |