Skip to content
Damjan Dabodabo.dev

Building in Public

Claude Code Made My App Store Screenshots in 13 Languages

Generating fully localized App Store screenshots with Claude Code and Codex: the complete Itemlist set across 14 storefronts, review gates that caught real bugs, and my only job was feedback.

A grid of localized Itemlist App Store screenshots in 13 languages, with the headline Claude Code made fully localized App Store screenshots

Itemlist's App Store screenshots now exist in 13 languages across 14 storefronts, on iPhone and iPad. That is 224 finished images. Claude Code made all of them. It captured the app in the simulator, wrote and localized every caption, rendered every set, and had a second AI review the results before I ever saw them. I did no manual work. My entire contribution was feedback, the same way you'd give a designer feedback between revisions.

The app itself was already localized. The store listing was the gap: every storefront showed the same English screenshots. Localizing them is not hard, it just takes a lot of time and is annoying. Eight screenshots, 14 storefronts in 13 languages (es-ES and es-MX are both Spanish, adapted per region), iPhone and iPad variants, and every caption, capture, and render has to be right in languages I mostly cannot read. The kind of task that never gets done by hand.

What actually ran

A DEBUG build of the app launches in the iOS Simulator with seeded demo data, once per locale. Claude Code drives it and captures the real screens. App pixels are a hard rule in my setup: the screen inside a screenshot is always a real capture of the shipped UI, never a marketing composite. The one exception is the barcode scanner, because Apple's VisionKit will not run on a simulator, so that screen is an HTML replica of the exact real layout.

The backgrounds behind the devices are generated too: gpt-image-1 made one wide panorama, which a script upscaled and cut into eight slices at exact screenshot size. Swiping through the gallery reads as one continuous scene.

Two finished Itemlist screenshot sets side by side: the German iPhone strip and the Japanese iPad strip, eight shots each, sharing one continuous background scene

Captions live outside the templates, one JSON file per locale. Claude Code translated them from the English set, then pushed every batch through text reviews by Codex, a second AI checking the first one's work. Those rounds caught real problems: wrong decimal separators, awkward interjections, review-card copy that came out too thin in translation, and one review claim that didn't trace back to a real review, so the claim got cut. Every claim in a screenshot has to trace to a source.

Then every locale renders through a script with a built-in caption-fit lint. It measures whether each headline actually fits its box, and a deliberately broken fixture proves the lint still fails when text clips. After rendering, Codex reviews the finished images per locale: clipped text, garbled glyphs, mid-word breaks, captions that don't match the UI language, wrong screens. At the end, contact strips let me approve a whole locale at a glance.

The screenshot pipeline as a flow of eight stages, with Claude Code producing, Codex reviewing at two points, and my sign-off as the final gate

Lifetime revenue per country decided the locale list: a language made the cut when its storefronts had earned it with real sales, so Dutch is in and some bigger languages are not.

The screenshots are not allowed to lie

The first screenshot shows a rating claim, and a baked screenshot must not make a claim one bad review can flip false. So the numbers are fetched per storefront from Apple's public lookup API at render time, and gated by a floor: a local rating only appears with at least 20 ratings behind it.

The US qualifies with 197 ratings at 4.7, Germany with 47 at 4.8. Those keep their own numbers, each naming its market: "4.7 average in the US", "4,8 Sterne in Deutschland". France had 16 ratings, Italy 6, Mexico 7, Sweden 6, too thin to quote, so their screenshots cite the US average instead, attributed to the US. Storefronts where the local average is genuinely low do the same, because a row of five stars next to a weak local average would read dishonest. The "36,000+ users" line that runs across the set is the lifetime customer count in RevenueCat, rounded down.

Bar chart of rating counts per storefront against the 20-rating floor: the US with 197 and Germany with 47 show their own averages, while France, Mexico, Italy, and Sweden fall below the floor and cite the US 4.7 instead

The floor exists because of a real failure. Mid-run, one commit quietly put local averages on storefronts with one to three ratings. Japan briefly claimed 5.0 stars based on a single rating. The change got flagged in review, audited, and reverted, and the 20-rating floor became a hard rule in the pipeline.

The screenshots found bugs in the app

Capturing a real app in 14 locales turns out to be accidental QA. The runs surfaced four localization bugs: demo seed values that rendered as absurd amounts in yen and won, Norwegian text leaking into the Danish version, a wrong screen title in Norwegian, and clumsy value phrasing in Japanese and Korean. All four got tickets in the app repo and got fixed.

The reviewer needed reviewing too

Languages need different amounts of space for the same sentence, so one shared layout can't hold them all: the type sizing has to adapt per locale. Swedish, Dutch, Danish, and Norwegian headlines needed lower size ceilings to stop overflows, and Japanese and Korean needed their own because CJK characters run wide. Korean headlines broke mid-word. バーコード, the Japanese word for barcode, split across two lines. The fixes were small locale-scoped CSS rules, not fourteen forked templates. The Japanese line for "36,000+ users" renders as 3.6万人以上 and needed its headline dropped to 50px to hold a single line.

And the review layer itself produced false positives. Codex flagged "2950,00 €" as missing a thousands separator. It isn't missing: Italian and Spanish number formats don't put a separator in four-digit amounts. Grouping starts at 10,000. It also misread the narrow no-break spaces French uses as separators. Both went into the runbook as known false positives, so the next run doesn't fix correct things into wrong ones.

What I actually did

I picked the visual treatment from rendered variants, answered caption questions, made the honesty calls on ratings, and said yes or no at the gates. Everything else was Claude Code doing the work and Codex checking it: the captures, the translations, the renders, the review rounds, the fixes.

The whole process is now a written runbook: revenue-driven locale selection, the caption review lane, the fit lint, the per-locale image review, the rating floor. My next app reuses it as a checklist. Localized screenshots used to be the kind of chore that stayed on the someday list. Now it's a pipeline I rerun.

Written by

Damjan Dabo

Writing field notes from Croatia 🇭🇷

Newsletter

You'll know when I ship a new post.

Just the post. No marketing drip, no upsell ladder. Unsubscribe in one click.