ANTIGRAVITY LABJP
Articles/Integrations
Integrations/2026-06-09Advanced

Rebuilding Wallpaper Image Delivery Around Resolution Buckets — Letting an Antigravity Agent Own Conversion and Validation

Every new device resolution quietly makes a wallpaper app heavier. I stopped shipping one master image to every device and rebuilt delivery around resolution buckets, WebP/AVIF, and an edge redirect — then handed conversion and validation to an Antigravity agent. Real code and thresholds included.

Antigravity275Cloudflare3image deliveryAdMob9indie developer9

Premium Article

I'm Masaki Hirokawa, an artist and creator. I run a set of wallpaper apps with over 50 million cumulative downloads as a solo developer, and the cost that hurts the most is the dullest one: device resolutions keep multiplying a little every year. During the update that added the iPhone Air and 17 Pro, I looked at the delivery logs and froze. I was shipping the exact same enormous PNG — one master image — to a device 1080px wide and to one 1320px wide alike.

A wallpaper has a huge pixel count, and people swipe through dozens of them. If you return the master untouched, you transfer pixels that never reach the screen, every single time. When I supported three or four devices it was rounding error. The moment my supported resolutions crossed into double digits, transfer volume and the feel of thumbnail scrolling started to rot, slowly. This is the operational record of rebuilding that delivery layer into a resolution-bucket scheme and handing the tedious conversion and validation to an Antigravity agent.

When device resolutions scatter, delivery breaks quietly

Let me be honest up front: the breakage never shows up as a loud crash. Nobody writes "slow" in a review, and nothing lands in Crashlytics. Instead, the thumbnail list stutters just slightly, the load before an AdMob interstitial stretches out, and users on slow connections leave on the second image. In numbers, the average display time on the wallpaper detail screen had crept from 0.9s to 1.4s.

The cause was simple once I broke it down. My app held masters at 2160px wide and shipped them to everyone. On a 1080px device, exactly half the received pixels were thrown away at display time. For those discarded pixels, I was transferring roughly double the bytes every time. The more device types appear, the wider the gap between "the one image that fits" and "the one image I actually ship."

My grandfather, a temple carpenter, never used a timber whose dimensions did not fit. Rather than shaving a piece down to make it work, he cut each piece for the place it was going. Image delivery is the same: each device deserves an image prepared for its screen. The single obstacle was that hand-producing variants for every resolution is not realistic.

Stop shipping one master to every resolution — bucket design

Giving each device a dedicated image does not mean producing every resolution in 1px steps. Real device widths cluster discretely — 1080 / 1170 / 1206 / 1290 / 1320 — and wallpapers survive a few pixels of scaling without visible damage. So I round widths into eight buckets.

// resolution-buckets.ts
// Round a device's logical width (px) to the delivered image-width bucket.
// Pull neighboring devices into one bucket to keep variant count down.
export const BUCKETS = [828, 1080, 1170, 1242, 1290, 1320, 1440, 1620] as const;
 
export function pickBucket(deviceWidthPx: number): number {
  // Choose the nearest bucket >= device width (downscale, never upscale).
  for (const w of BUCKETS) {
    if (w >= deviceWidthPx) return w;
  }
  return BUCKETS[BUCKETS.length - 1];
}

There is one deliberate choice here. I pick the nearest bucket on the larger side of the device width. Stretching a small image makes a wallpaper blurry, but shrinking a slightly larger one lands cleanly. The master stays a single 2160px file, and every bucket's WebP and AVIF derive from it. Because there is exactly one original, adding a ninth bucket for a new device later is just a re-generation away.

I settled on eight buckets by working backward from my real device distribution: that is the step count needed to cover the top 99% of my DAU devices. A ninth bucket would benefit about 0.4% of users, while each extra variant grows storage and generation time by a non-trivial ratio. I set "top 99% in 8 steps" as my baseline.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
How rounding device widths into 8 buckets and deriving WebP/AVIF from a single master cut transfer by about 42%
Before/After edge-redirect code that returns exactly one optimal file per device, plus the Accept-header handling
The validation gate that halts agent-generated variants before production: aspect ratio, file size, and luminance checks
Secure payment via Stripe · Cancel anytime
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Integrations2026-05-23
Apple Search Ads × Antigravity Agent: Autonomous Keyword Bid Tuning Notes from an Indie iOS Studio
How I delegated Apple Search Ads keyword bidding to Antigravity sub-agents for a 50M-download wallpaper app portfolio. JWT auth, ROAS / CPI bid policy, and a Crashlytics-driven safety net.
Integrations2026-05-30
Diagnosing AdMob Mediation Fill Rate with an Antigravity Agent — A Memo on the Revenue I Lost Chasing eCPM Alone
When AdMob mediation revenue stalls, the cause is usually fill rate, not eCPM. This memo walks through a diagnostic pipeline that lets an Antigravity agent read your BigQuery export and Firebase metrics to isolate per-network fill rate drops automatically, with real numbers from indie development.
Integrations2026-05-28
Five Weeks Letting Antigravity's Background Agent Refresh App Store Screenshots Across Four Apps
An operations log from running Antigravity Background Agent for five weeks to keep the App Store screenshots for four wallpaper apps in sync across eight locales — including the boundaries I kept, the recurring failure modes, and what I learned about where automation should stop.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →