DEV Community

marsdiscovery
marsdiscovery

Posted on

App store screenshots are a data problem: three small browser tools from a team that kept resizing


Every solo app launch ends the same way. The build is green, the tests pass, and then the store asks for something nobody put on the roadmap: a screenshot for every possible device class, an icon in sizes you cannot remember, a 1024x500 feature graphic, and a set of rules that quietly change every time Apple shows a new iPhone.

We kept doing this by hand for our own releases. Two weeks later we had three browser tools instead of one evening of resizing, and they taught us more about the craft than the actual editing did.

Why we started

DevCove started as a plain developer toolbox: format, encode, generate, validate. Then shipping a small app made us face a pile of "pixel chores" that did not fit any of those categories. App Store wants a portrait, a landscape, an alt-display-size portrait. Google Play wants its own screenshots and a separate horizontal feature graphic. The sizes are close enough that you hope one export covers them, and different enough that it never does.

We are the team that runs the site, so we chose the polite path. No server, no upload, no login: the work happens in the browser or it does not happen at all. That single old constraint shaped every later decision.

The first tool: one canvas, many presets

The composer begins with raw screenshots of the real UI. A small canvas puts each screenshot under an optional headline and sub-headline, then renders the same document once per preset: 1290x2796 portrait, 1320x2868, landscape where the store accepts it.

The layout is not saved as pixels. It is saved as a document: canvas size, text boxes, per-preset transforms. Every render re-measures the text against the target box, shrinks it until it fits on the canvas, and reports when it overflows. The same file reads fine on whatever preset the stores ship next year.

That is the trade we made: template-based rendering instead of free-form drawing. You lose Photoshop-style art direction, and you gain the fact that the output is always the correct ratio. For us, a correct ratio was worth more than unlimited creative control. People scan the store page for a few seconds; consistency beats variety there.

Presets are data, not code

The resizer taught us the next lesson: a store requirement is a row in a table, not a function in your head.

The presets live as plain data:

type AppMarketPreset = {
  id: string;
  width: number;
  height: number;
  requirementLevel: "required" | "optional";
  officialUrl: string;
  defaultExportFormat: "image/png" | "image/jpeg";
};
Enter fullscreen mode Exit fullscreen mode

Each row carries its official documentation link, so the UI can show "required" or "optional" next to the exact size, and open the platform page for the ones that confuse us. When Apple shipped the 6.9-inch display set, adding the new sizes meant adding rows and a test, not reworking the tool.

The same data also drives the export checklist. Pick iPhone 6.9 portrait and the tool tells you which official result to check, in which format, with the requirement flag visible. It is the mechanical part of the job, minus the guesswork.

Icons without AI generation

The third one is the quietest decision. The icon generator does not generate an icon. It takes the logo the team already owns, lets you crop it or pad it (cover vs contain), sets a background color, and exports the PNG sizes for iOS, Android, and both stores in one ZIP.

People sometimes ask why we did not wrap it in a "generate icon" model. The reason is practical: the logo is shipped artwork. A model will invent a variation that does not match the product, and the store then front-shows a drawing nobody signed off on. Cropping, padding, and sizing the real master is the boring, correct job.

What the schema kept us honest about

The three tools use the same canvas primitives, so the shared code is small: load an image, crop it, scale it, export a Blob. The interesting parts are all data and rule: the preset table, the requirement flag, the official link. That is also where the bugs can hide.

A few things we learned the hard way:

  • Common sizes drift over time. Text renders fine in one ratio and wraps wrong in another; the re-measuring step exists because of that.
  • "Required" means required. If a store really wants a specific display size, shipping the old one is not a smaller mistake, it is the same mistake at a different ratio.
  • Promotional rules are per platform. Google discourages "Install now" style wording inside artwork, Apple is strict about safe areas and text density. The copy checker matters as much as the sizes.

Where it leaves the process

We build DevCove, and these three are browser tools we shipped because a small team cannot afford endless export rounds. The composer, the market resizer, and the icon generator are grouped into a single app store assets category, and the category page keeps the platform order so the flow lines up with the actual list the store gives you.

The heavy lifting is boring on purpose. The tooling does not make art; it makes sure the fields you do send are the fields the store expects, in the files that require them.

A question for you, since dev.to is where the patterns are shared: when Apple announces a next display size, do you update screenshots as data or open a design tool and start over? We are still investing in presets-as-data; I would be honestly curious what that investment looks like four devices from now.

Top comments (0)