Reference · generated from the build code

Every icon file
your platform
actually needs.

Favicon, PWA manifest, Tauri, Electron and the macOS menu bar — one table per target, with the exact filenames and frame sizes. Nothing here is transcribed by hand: the page is generated from iconflow/build.py, so it says what the tool ships and fails the build when the two disagree.

IconFlow 0.6.0 · targets: web, pwa, tauri, electron, tray, emote

Web favicon

The modern set is smaller than most guides claim. An SVG covers every current browser at every size; the .ico exists only for legacy fallback, and it is one file, not three.

iconflow ship --targets web
FileSizeWhy it exists
favicon.svgvectorPrimary in every current browser. Scales to any size, one file.
favicon.ico16 · 32 · 48 px framesLegacy fallback. One container, three frames — not three files.
apple-touch-icon.png180 × 180 pxiOS home screen. Flattened onto the background colour: iOS ignores alpha.
icon-192.png192 × 192 pxAndroid home screen and the PWA install prompt.
icon-512.png512 × 512 pxSplash screens and store listings.
icon-512-maskable.png512 × 512 pxAdaptive icon. Artwork inset 10% per side and flattened, so no platform mask can remove part of the mark.
site.webmanifestJSONDeclares the three PNGs, theme colour and display mode.
favicon-head.htmlHTMLThe paste-ready <head> block, generated with the assets.

The <head> block

IconFlow writes this next to the assets as favicon-head.html, so the markup and the files are produced together and cannot disagree:

<!-- Paste into <head>. SVG is primary; .ico is the legacy fallback. -->
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="theme-color" content="#0b0d12">

PWA manifest and maskable icons

An adaptive platform crops your icon to a shape it chooses. A square drawing that reaches the canvas edge loses its corners; one with transparency shows the mask through. Both problems are solved before export, by insetting the artwork and flattening it onto the background colour.

The generated site.webmanifest declares exactly three icons — the third carrying "purpose": "maskable":

{
  "name": "My App",
  "short_name": "My App",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/icon-512-maskable.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ],
  "theme_color": "#0b0d12",
  "background_color": "#ffffff",
  "display": "standalone",
  "start_url": "/",
  "scope": "/"
}

Safe zone. The maskable asset insets the artwork 10% on every side, leaving it at 80% of the canvas, then flattens it. Any platform mask — circle, squircle, rounded square — lands inside that margin.

Windows pinned-site tiles optional

Only produced with --windows-tiles. The artwork is centred on each canvas rather than stretched, which is why the wide tile takes a smaller scale than the squares.

iconflow ship --targets web --windows-tiles
FileSizeWhy it exists
mstile-70x70.png70 × 70 pxSmall pinned-site tile.
mstile-144x144.png144 × 144 pxLegacy pinned-site tile.
mstile-150x150.png150 × 150 pxMedium tile.
mstile-310x310.png310 × 310 pxLarge tile.
mstile-310x150.png310 × 150 pxWide tile — the one rectangle in the set.
browserconfig.xmlXMLPoints at the tiles and sets the tile colour.

Tauri

Five PNGs plus the two desktop containers. The ICO frame order matches the Tauri CLI's own output, so the result drops into src-tauri/icons/ unchanged.

iconflow ship --targets tauri
FileSizeWhy it exists
icons/32x32.png32 × 32 pxPNG, written into src-tauri/icons/.
icons/64x64.png64 × 64 pxPNG, written into src-tauri/icons/.
icons/128x128.png128 × 128 pxPNG, written into src-tauri/icons/.
icons/128x128@2x.png256 × 256 pxRetina pair for the 128 pixel tile.
icons/icon.png512 × 512 pxThe Tauri source image.
icons/icon.ico32 · 16 · 24 · 48 · 64 · 256 px framesWindows. Frame order matches the Tauri CLI's own output.
icons/icon.icns16 · 32 · 64 · 128 · 256 · 512 · 1024 px framesmacOS bundle icon.

Electron

electron-builder reads one source image per platform. The optional corner radius is applied to the raster frames only — your SVG master keeps its own geometry.

iconflow ship --targets electron
FileSizeWhy it exists
build/icon.png1024 × 1024 pxLinux, and the electron-builder source image.
build/icon.ico32 · 16 · 24 · 48 · 64 · 256 px framesWindows installer and window icon.
build/icon.icns16 · 32 · 64 · 128 · 256 · 512 · 1024 px framesmacOS app bundle.

macOS menu bar and system tray

This is the target that fails most often, and it fails silently: a template image carries no colour at all. macOS reads its alpha channel and paints the shape itself, so a full-card app icon with an opaque background arrives as a solid black rectangle.

iconflow ship --targets tray
FileSizeWhy it exists
tray/tray.png32 × 32 pxColour tray icon at 2× density.
tray/tray@16.png16 × 16 pxColour tray icon at 1× density.
tray/trayTemplate.png16 × 16 pxmacOS template: pure black plus alpha. The system recolours it.
tray/trayTemplate@2x.png32 × 32 pxRetina template pair. Required, not optional.
tray/trayIcon.tsTypeScriptOptional inline data-URL module (--tray-ts).

Give the tray its own drawing. A menu bar mark needs real transparency around a sparse shape — usually a simplified version of the master, not the master itself. Pass it with --tray-svg. When you do not, IconFlow derives alpha from the mark's contrast, and if no semantic shape can be isolated it refuses the build rather than shipping a black square.

Chat emotes

An emote is judged smaller than its upload and on two backgrounds at once: Twitch draws it at 28 pixels, Discord and Slack at roughly 22 to 32, on white and on dark chat alike. Each size below is rendered natively from the SVG, not scaled down from the largest, and a file over its platform's upload limit fails the build instead of the upload form. all builds the app-icon targets; ask for emote by name.

iconflow build master.svg --targets emote
FileSizeWhy it exists
emote/28.png28 × 28 pxTwitch, as shown in chat. Uploaded with 56 and 112; at most 25 KB.
emote/56.png56 × 56 pxTwitch, 2× density. At most 25 KB.
emote/112.png112 × 112 pxTwitch, 4× density and the size Twitch reviews. At most 25 KB.
emote/128.png128 × 128 pxDiscord and Slack custom emoji. At most 128 KB (Slack's limit; Discord allows 256 KB).

Why 16 pixels decides everything

Every size in the tables above is rendered from the same SVG, but only one of them is where icons actually fail. At 16 pixels a counter closes, a hairline vanishes, and two adjacent colours average into one. A design reviewed at 1024 pixels and exported downward can be unreadable in the browser tab it was made for — and the export step will not tell you.

IconFlow inverts the order. It renders native pixels through a pinned Chromium at every target size, shows you the result at 1:1, and ship fails closed unless automated checks are clean and all six human rubric scores are at least 4 out of 5.

Questions people ask

How many favicon files does a website actually need in 2026?

Six, plus a manifest. An SVG favicon for current browsers, a legacy favicon.ico holding the 16, 32 and 48 pixel frames, a 180 pixel apple-touch-icon.png, and 192, 512 and maskable 512 pixel PNGs declared in the web app manifest. Sets larger than this are almost always carrying files no current platform requests.

What sizes go inside favicon.ico?

16, 32 and 48 pixels. ICO is a container format, so those three frames live inside one file — you do not ship favicon-16.png and favicon-32.png alongside it.

What is the maskable icon safe zone?

Android and other adaptive-icon platforms crop your icon to a shape they choose, so anything near the edge can be cut. IconFlow insets the artwork 10% on each side — leaving it at 80% of the canvas — and flattens the result onto the background colour, so no mask can remove a meaningful part of the mark or reveal transparency.

Why is my macOS menu bar icon a black square?

A macOS template image carries no colour: the system reads only its alpha channel and paints the shape itself. Handing it a full-card app icon whose background is opaque therefore produces a solid black rectangle. The fix is a separate tray drawing with real transparency around a sparse mark. IconFlow detects the failure instead of shipping it: when a source covers too much of the canvas it derives alpha from the mark's own contrast, and refuses the build outright if no semantic shape can be isolated.

What icon sizes does Tauri need?

Five PNGs — 32, 64, 128, 256 (as 128x128@2x.png) and 512 — plus icon.ico for Windows and icon.icns for macOS. IconFlow writes the ICO frames in the same order the Tauri CLI does, so the output is a drop-in replacement.

What icon sizes does Electron need?

A 1024 pixel PNG for Linux and as the electron-builder source, an ICO for Windows and an ICNS for macOS. The container frames are the same desktop set used everywhere else: 16, 24, 32, 48, 64, 128, 256, 512 and 1024 pixels, selected per format.

Can I just resize a 1024 pixel PNG down to 16 pixels?

You can, and that is exactly where most icons fail. At 16 pixels a counter closes, a hairline disappears and two colours average into one. Downscaling produces the file but tells you nothing about whether the result is still readable. IconFlow renders every size from the SVG through a pinned Chromium and shows you the native pixels before anything ships.

Does IconFlow upload my artwork or call an image model?

No. There is no image model and no API key. You author the SVG, a pinned local Chromium renders it exactly as a browser would, and every file is written on your machine. The only network step is the one-time Chromium download.

Who owns the icons made with IconFlow?

You do. No attribution is required, there is no share-alike obligation on your output, and commercial use is unrestricted. Run iconflow license for the full answer.

One master. Every surface.

Stop exporting.
Start proving.

Everything on this page is one command away, and the first run is a genuine gated ship rather than a render.

pip install iconflow
iconflow setup
iconflow demo --out iconflow-demo