Why I swapped custom screenshots for Apple's App Store preview videos
App Store previews are already the best footage of your iOS app. Here's how I pulled them into my landing page — and the one gotcha that bit me.
I spent a weekend building a landing page for Island & Pine — a shelf for the seven small apps I ship under the studio name. Three of them are iOS games: JellySplit, Cell Division, and Jelmata. The obvious thing to put on the page is a phone mockup showing each game in action.
The obvious thing is also where I wasted my first evening.
The screenshot trap
The first instinct, if you’ve done any marketing design, is to open Figma, drop in a phone frame, and composite a hero screenshot. It feels productive. You pick a satisfying moment from the game, you crop, you nudge, you export at 3x. Then you look at it and it’s… fine. Static. A frozen moment that doesn’t tell you why the game is interesting.
What made me stop was opening the App Store listing next to my Figma file and realizing I already had the better asset. The App Store preview video — the thing Apple makes you record if you want to feature your app properly — is silent, looping, portrait, and shows motion. It’s exactly the shape a landing-page hero wants. And every one of my games already had one, because Apple required it when I submitted.
I was reinventing the asset I’d already produced.
Grabbing the file
App Store previews are hosted on Apple’s CDN and the players on the web are just HTML5 <video> elements. You can pull the source a few ways:
- Right-click → “Save Video As” on the player at
apps.apple.com/us/app/<your-app>. Works in Safari and Chrome. Easiest path. - DevTools → Network tab → filter for
.mp4or.m3u8→ reload the page → right-click the request and copy the URL. Useful if the context menu is locked out. - App Store Connect → Media Manager. This is the cleanest source because it’s your original upload before Apple’s re-encode.
I used #1 for the three games already live, then dropped the .mp4s straight into public/previews/. For the poster frame — what shows before autoplay kicks in — I grabbed the first frame with ffmpeg:
ffmpeg -i previews/jellysplit.mp4 -ss 0 -frames:v 1 previews/jellysplit.jpg
Wiring it into Astro
The landing page uses a single DeviceFrame.astro component that renders either a phone or a laptop. The change was small: accept an optional preview: { src, poster } prop, and if it’s there, render <video> instead of <img>.
{hasPreview ? (
<video
class="phone-shot phone-video"
src={preview!.src}
poster={preview!.poster}
autoplay
loop
muted
playsinline
preload="metadata"
aria-label={`${name} preview`}
/>
) : (
<img src={screenshot} alt={`${name} screenshot`} />
)}
Two attributes on that <video> tag are non-negotiable on iOS Safari: muted and playsinline. Without muted, autoplay is blocked (browsers won’t autoplay audio without a user gesture). Without playsinline, tapping the video on iPhone kicks it into full-screen native playback, which is the opposite of what you want on a landing page. I’ve seen both of these missed in production apps more than once. They fail silently — autoplay just… doesn’t — so it’s easy to ship broken and not notice.
The preload="metadata" is a small politeness: it tells the browser to fetch just enough to know the duration and first frame, not the whole file. Combined with poster, the video feels instant even when the .mp4 is still loading in the background.
The gotcha: file size
Here is the part I wish I’d thought about first. Apple’s original App Store preview file for JellySplit was about 3 MB after the “Save As”. For a hero asset on a landing page hero — three of them, all autoplaying on first paint — that’s too much. On a phone on LTE you’d see the poster frame and then a long, silent wait.
A one-liner through ffmpeg knocked it way down:
ffmpeg -i in.mp4 -c:v libx264 -crf 28 -vf scale=720:-2 -an -movflags +faststart out.mp4
A few pieces worth knowing:
-crf 28is the quality knob. Lower is better quality; 28 is at the “you won’t notice” edge for small-screen looping video. 23 is the default, but default is overkill for something that’ll be rendered inside a 240-pixel-wide phone frame on a webpage.-vf scale=720:-2scales the video to 720px wide. The-2means “pick an even height that preserves aspect ratio” (even is required by most codecs). The original is probably 1080p or higher; you don’t need that inside a CSS-constrained phone mockup.-anstrips the audio track. App Store previews are silent by design, so any audio is just wasted bytes.-movflags +faststartmoves the MP4 metadata to the start of the file so the browser can begin playback before the file is fully downloaded. This one is genuinely important for perceived speed.
After that pass, JellySplit’s preview went from ~3 MB to 1.1 MB. The others landed at 290 KB and 630 KB. All three combined are now smaller than a single stock-photo hero image, which feels like the correct cost for “three autoplay videos.”
When not to do this
This approach works well for games because the App Store preview format — motion, no audio, portrait — is the format. It works less well for utility apps where the App Store preview is a narrated “tap here, swipe there” tour. That kind of preview tells you how to use the app, which isn’t what a landing page wants; a landing page wants to tell you why. For those, custom-composited screenshots (or a purpose-built loop) still win.
The thing I’d keep from the whole exercise is more general than the specific trick: before producing a new asset, check whether you already produced it for a different channel. App Store previews, press kit screenshots, onboarding illustrations, the marketing copy you wrote for the App Store description — these are all things you’ve already spent effort on, and the marginal cost of reusing them on the web is near zero. I have a suspicion this applies to a lot more than iOS previews.
If you want to see the end result, the three games with App Store previews are on the Island & Pine home page. JellySplit is the pink hex puzzle; Cell Division is the blue board game; Jelmata is the green cluster game.