What icons a PWA really needs
A Progressive Web App (a website that can be added to the home screen like an app) doesn't need one icon, it needs many: different sizes for different devices and purposes. The PWA generator takes one image and produces the complete set from it. Concretely, that's the sizes 72, 96, 128, 144, 152, 192, 384, and 512 pixels — plus special cases we'll get to in a moment. The basics of why these sizes are needed are covered in the post Building a PWA — a guide.
Step 1: render each size individually
For each target size, a canvas is created at exactly those dimensions, the source image is drawn into it, and it's exported as a PNG via toBlob():
canvas.toBlob(blob => { ... }, "image/png");Eight sizes = eight repetitions of the same small operation. Because PNG is lossless, the icons stay sharp; and because everything runs locally, the logo never leaves your computer.
Step 2: the maskable trap
This is where it gets interesting. Depending on the manufacturer, Android lays different shapes over app icons — circle, rounded square, teardrop. A normal icon that extends all the way to the edge gets clipped at the corners. The solution is called a maskable icon: a variant with extra margin all around — the safe zone — so the mask only trims that margin and the subject always stays intact.
That's why the generator additionally creates maskable variants for the important sizes (192 and 512 px) with plenty of safety margin — the subject sits smaller and more centered in the canvas. In practice that means: you don't design the icon edge-to-edge, you give it about 10–20% of breathing room toward the outside. Forget that, and your icon gets nibbled on some Android devices.
Step 3: write the manifest.json
For the browser to associate the icons with a PWA, you need a manifest file — a JSON file that describes the name, colors, start page, and, crucially, the icon list with its sizes and purposes (purpose). The generator assembles this file automatically with the right entries, including the distinction between normal (any) and maskable icons. You get it ready to paste in — no manual JSON typing, no forgotten commas.
Step 4: bundle it all
At the end there's a whole package: eight to ten PNG files plus the manifest.json. Instead of downloading them one by one, the generator packs them into a ZIP archive — in the browser, without a server. How this batch bundling works technically is a small topic of its own, covered in the workshop notes on batch processing.
What we learned from it
Two things stuck with us. First: the real work isn't in the scaling (that's a one-liner) but in the special cases — maskable, Apple touch icon, the right manifest entries. If you only generate the standard sizes, you've done 80% of the work and left 100% of the headaches behind. Second: a generator is only as good as its knowledge of the target platforms. The sizes and the safe-zone rule aren't a math problem, they're platform knowledge that comes from documentation and trial and error — exactly the kind of detail that makes a tool valuable.