Skip to content
OmniTools

PWA Manifest & App Icon Generator

Generate progressive web app manifests, iOS, Android adaptive icons, Windows tiles and splash screens in one ZIP. Free in-browser PWA asset studio.

PWA manifest & asset studio

How it will look once installed

Add a master image and the simulator renders the real generated icons here.

Manifest audit

  • note — No description. The manifest description is used in some install dialogs and by a few app directories; it is cheap to write one.

An error here means the install prompt will not appear or will resolve to the wrong app. A warning means it installs but something looks wrong on a real device.

manifest.webmanifest
index-head-tags.html — the <head> tags
next-metadata.txt — the same intent as a Next.js metadata export

What is in the bundle, and why

Android & manifest icons

Purpose any, plus the maskable variant Android crops by the launcher's own mask.

48 × 48 — Android / PWA manifesticon-48x48.png
A ladder rung for launcher surfaces and older Android versions that ask for their own size.
72 × 72 — Android / PWA manifesticon-72x72.png
A ladder rung for launcher surfaces and older Android versions that ask for their own size.
96 × 96 — Android / PWA manifesticon-96x96.png
A ladder rung for launcher surfaces and older Android versions that ask for their own size.
144 × 144 — Android / PWA manifesticon-144x144.png
A ladder rung for launcher surfaces and older Android versions that ask for their own size.
192 × 192 — Android / PWA manifesticon-192x192.png
The smallest size Chrome accepts in an install prompt. Below this it refuses the manifest.
512 × 512 — Android / PWA manifesticon-512x512.png
The splash-screen and install-dialog size, and the canvas the maskable icon is cut from.
512 × 512 — maskable (Android adaptive)icon-512x512-maskable.png
Android crops this by the launcher's mask, so the logo is kept inside a 410px safe circle and the rest is filled.

iOS home screen & Spotlight

Square and opaque, because iOS rounds the corners itself and composites alpha against black.

152 × 152 — iOS spotlight / older deviceapple-touch-icon-152x152.png
Read by older iOS versions and by Spotlight. Harmless to ship, and it saves a legacy device.
167 × 167 — iOS spotlight / older deviceapple-touch-icon-167x167.png
Read by older iOS versions and by Spotlight. Harmless to ship, and it saves a legacy device.
180 × 180 — iOS home screenapple-touch-icon.png
The only iOS size Safari still reads. iOS applies its own rounding and composites transparency against black, so this file is square and opaque.

Windows tiles

Referenced by browserconfig.xml, which Windows reads instead of the manifest.

150 × 150 — Windows tilemstile-150x150.png
Declared in browserconfig.xml. Without it, pinning the site to the Windows start menu uses a scaled screenshot.
310 × 310 — Windows tilemstile-310x310.png
Declared in browserconfig.xml. Without it, pinning the site to the Windows start menu uses a scaled screenshot.

Favicons

The PNGs go in <head>; the .ico is the fallback for a request with no link tag at all.

16 × 16 — PNG faviconfavicon-16x16.png
What a desktop browser tab actually draws. Everything above 16px is only seen on HiDPI screens.
32 × 32 — PNG faviconfavicon-32x32.png
The HiDPI tab icon, and the fallback when a browser ignores the .ico.

favicon.ico

One container holding 16, 32, 48px images as PNG payloads. Modern browsers read PNG inside an .ico, so the older BMP/DIB branch of the format is not produced.

Splash screens

A flat #ffffff field with the icon centred at 28% of the short edge. One ratio rather than a pixel size per device, so the same rule looks deliberate on a phone and a tablet.

1080 × 1920 — Android 9:19.5 phonesplash-1080x1920.png
1440 × 3120 — tall 19.5:9 Androidsplash-1440x3120.png
1920 × 1080 — landscapesplash-1920x1080.png
1284 × 2778 — iPhone 15/16 Pro Maxsplash-1284x2778.png

browserconfig.xml

Not part of the web app manifest and read by a different subsystem entirely, which is why a fully valid PWA can still pin to the Windows start menu with a grey screenshot.

Every icon is resampled from your master image. The archive is store-only: PNG is already deflated, so compressing it again costs CPU and usually saves nothing. Nothing is uploaded.

A manifest does not make an app work offline

Installability comes from the manifest, the icons and a service worker. The service worker is what caches the shell, updates it in the background and lets the app launch with no network at all. The tags above register one at /sw.js, which you still have to write and ship — and browsers will refuse the install prompt entirely on anything not served over HTTPS.

This tool runs entirely in your browser. Nothing you enter is uploaded, stored, or logged.

What this tool does

A progressive web app is installable only if a specific set of files exists, and almost none of them are hard to find one at a time: an icon at every size Chrome will ask for, a maskable variant Android can crop, three Apple touch icons Safari reads, two Windows tiles, a favicon, a manifest, and the head tags that make a browser notice any of it. Collecting that by hand means resizing one square nine times and hoping the filenames match what the manifest points at. This studio takes a single master image and returns the whole bundle, with the manifest and the link tags generated from the same filenames as the images.

How it works

The manifest is where most of the real work is, and the two fields people get wrong are scope and start URL. Scope is matched as a URL prefix, not treated as a folder name, which is why a scope of /app quietly swallows /application while leaving out /app/dashboard. The start URL has to sit inside the scope, or the installed copy launches somewhere the browser considers a different application entirely and loses its storage and its session. Those two values are checked against each other before anything is written, and a scope missing its trailing slash is flagged with the corrected form.

Icons are resampled from the master image with the canvas API, and the interesting one is the maskable icon. Android crops an adaptive icon by whatever mask the launcher applies — a circle, a squircle, a rounded square — so everything that matters has to sit inside a circle covering roughly 80% of the canvas. On a 512 pixel icon that is a 410 pixel safe zone. The logo is inset to fit inside that circle and the background is filled in behind it, so whatever the launcher cuts away is still solid colour rather than transparency.

Every platform reads a different subset of this bundle and ignores the rest. iOS never reads the manifest for icons at all; it takes only the apple-touch-icon links, applies its own corner rounding, and composites transparency against black rather than against your page, which is why the Apple icons are flattened onto the background colour instead of shipping with an alpha channel. Windows ignores both the manifest and the link tags and reads browserconfig.xml, which belongs to a different subsystem and fixes the grey-screenshot tile problem on its own.

The archive is assembled in the browser and written without a compression library. It is store-only rather than deflated, which is the honest choice for this particular payload: the files are PNGs, which are already deflated, so running the algorithm over them again costs CPU and usually saves nothing. Nothing is uploaded anywhere. The manifest, the browserconfig tile file, the HTML head tags and the Next.js metadata object are all produced from the same filename helpers the images are written with, so the references cannot drift away from the files that were actually generated.

Worked example

A client wants a React app installable on both iOS and Android, starting from one 1024 × 1024 PNG logo.

  1. The logo is resampled across the Android ladder from 48 to 512, with a separate 512 maskable icon whose logo is inset inside the 410 pixel safe circle
  2. Three Apple touch icons are produced at 180, 167 and 152, each flattened onto the background colour because a transparent iOS icon ships as a black square
  3. Two Windows tiles and a browserconfig.xml are added so pinning the site to the start menu uses an icon rather than a screenshot
  4. favicon.ico is packed with 16, 32 and 48 pixel images, and manifest.webmanifest is written with start_url and scope both at / so the two agree
  5. The head tags are pasted into the document head and the bundle is unzipped into the public directory

A bundle covering every icon size, both splash sets, the manifest and the tile XML, where every src the manifest declares points at a file that is actually in the zip.

Accuracy and limitations

  • A manifest does not make an app work offline. That requires a service worker, and the tag this tool prints only registers one at /sw.js if you have written it yourself.
  • iOS draws its own splash screens from the launch image and the operating system, not from the manifest. The generated splash PNGs are for Android and for any builder that asks for them by filename.
  • Icons are resampled from your master image, so scaling past the master's own pixel count produces soft edges. 512 × 512 is the useful floor; 1024 × 1024 is better.
  • Nothing here adds HTTPS, a service worker or a cache. Browsers will also suppress the install prompt entirely for a site not served over a secure context.

Frequently asked questions

Do I still need a service worker if I have a manifest?
Yes. The manifest makes a page installable; it does nothing for offline use, caching or updates. Everything a home-screen icon promises about launching into a working app comes from a service worker. The head tags printed here register one at /sw.js, which you still have to write and ship.
Why is my Android icon getting its corners cut off?
Because an icon declared with purpose "any" is treated as a full-bleed square and cropped by the launcher's own mask, which is usually a circle or a squircle. The fix is the maskable variant, where meaningful content sits inside a circle covering about 80% of the canvas. This tool generates it at 512 with the logo inset into a 410 pixel safe zone.
What is the difference between start_url and scope?
start_url is where the installed app opens; scope is the URL prefix the app is allowed to control. If start_url falls outside scope, the installed copy launches somewhere the browser treats as a different app, so storage and session are not shared with the tab you installed from. Scope is also a prefix match, so /app includes /app/dashboard and also /application.
Can I use an SVG as my master image?
Not here, and the reason is decoding rather than format support. Browser canvas rasterisation of an SVG needs the markup parsed before it can be drawn, which does not fit the same pipeline that decodes your PNG or JPEG once and resamples from pixels. Export your SVG to a 1024 × 1024 PNG first, which is also what every launcher wants to be handed anyway.
Is my logo uploaded to a server anywhere?
No. Decoding, resizing, masking and zipping all happen in the browser tab using the canvas API and a small ZIP writer, so an unreleased brand mark or a client's logo never leaves the machine. The manifest, the head tags and the tile XML are string templates produced in the same tab.