A fast, interactive CLI to generate PWA icons for iOS, Android, Windows 11, and favicons from a single source image.
Built with Bun, Sharp, and @clack/prompts.
export-1769346706706440-demo.mp4
- Interactive prompts — No need to remember flags
- 118 icons generated in under 1 second
- Smart edge detection — Samples border pixels for seamless backgrounds
- Multiple output formats — PNG, WebP, AVIF, JPEG
- Optimization levels — Balance quality vs file size
- Platform selection — iOS, Android, Windows 11, Favicon
- Favicon generation — Multi-size ICO + apple-touch-icon
# Run interactively
bun run start
# Or with flags
bun run start -i logo.png -o ./icons -y# npm
npx pwa-icons
npm install -g pwa-icons
# yarn
yarn dlx pwa-icons
yarn global add pwa-icons
# pnpm
pnpm dlx pwa-icons
pnpm add -g pwa-icons
# bun
bunx pwa-icons
bun add -g pwa-iconsPrerequisites: Bun v1.0.0+ or Node.js v18+
# Clone the repo
git clone https://github.com/SivaramPg/pwa-icons.git
cd pwa-icons
# Install dependencies
bun install # or: npm install
# Run
bun run start # or: npm startJust run without arguments:
bun run startYou'll be prompted for:
- Source image path — Must be square, minimum 256×256px
- Output directory — Default:
./AppImages - Platforms — iOS, Android, Windows 11 (multi-select)
- Output format — PNG, WebP, AVIF, or JPEG
- Padding — 0 to 1 ratio (0.3 recommended)
- Background color — Edge detection, transparent, or custom hex
- Optimization level — None, light, or heavy
For scripting or CI/CD:
bun run start \
-i logo.png \
-o ./output \
-p ios,android \
-f webp \
--padding 0.3 \
-b edge \
--optimization light \
-y| Flag | Description | Default |
|---|---|---|
-i, --input <path> |
Source image path | (required in non-interactive) |
-o, --output <path> |
Output directory | ./AppImages |
-p, --platforms <list> |
Comma-separated: ios,android,windows11,favicon |
ios,android,windows11 |
-f, --format <fmt> |
png, jpg, webp, avif |
png |
--padding <0-1> |
Padding ratio | 0.3 |
-b, --background <color> |
edge, transparent, or hex color |
edge |
--optimization <level> |
none, light, heavy |
light |
-y, --yes |
Skip confirmation prompts | false |
Generate icons in a GitHub Actions workflow:
- name: Generate PWA Icons
run: npx pwa-icons -i ./src/logo.png -o ./public/icons -ynpx pwa-icons -i logo.png -p favicon -ynpx pwa-icons -i logo.png -f webp --optimization heavy -ynpx pwa-icons -i logo.png -b transparent -f png -ynpx pwa-icons -i logo.png -b "#1a1a2e" -ynpx pwa-icons -i logo.png --padding 0 -ynpx pwa-icons -i logo.png -p ios,android -ynpx pwa-icons -i logo.png -p ios,android,windows11,favicon -y| Format | Extension |
|---|---|
| PNG | .png |
| JPEG | .jpg, .jpeg |
| WebP | .webp |
| AVIF | .avif |
| SVG | .svg |
| GIF | .gif |
| TIFF | .tiff |
| Format | Transparency | Best For |
|---|---|---|
| PNG | ✅ | Maximum compatibility |
| WebP | ✅ | Modern browsers, ~8x smaller |
| AVIF | ✅ | Next-gen, smallest files |
| JPEG | ❌ | Universal support |
Samples 1px from all four edges of your image and calculates the average color. This creates seamless backgrounds that naturally extend your image.
-b edgeOnly available for PNG, WebP, and AVIF:
-b transparentAny hex color:
-b "#ff6b6b"
-b "#fff"| Level | PNG | JPEG | WebP | AVIF |
|---|---|---|---|---|
none |
compression: 4 | quality: 90 | lossless | quality: 85 |
light |
compression: 6 | quality: 85, mozjpeg | quality: 85 | quality: 75 |
heavy |
compression: 9, palette | quality: 75, mozjpeg | quality: 75 | quality: 60 |
| Format | Optimization | Size |
|---|---|---|
| PNG | light | ~34 KB |
| WebP | heavy | ~4 KB |
| AVIF | heavy | ~3 KB |
AppImages/
├── ios/
│ ├── 16.png
│ ├── 20.png
│ ├── ...
│ └── 1024.png # 26 icons
├── android/
│ ├── android-launchericon-48-48.png
│ ├── android-launchericon-72-72.png
│ ├── ...
│ └── android-launchericon-512-512.png # 6 icons
├── windows11/
│ ├── SmallTile.scale-100.png
│ ├── Square150x150Logo.scale-100.png
│ ├── LargeTile.scale-100.png
│ ├── SplashScreen.scale-100.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── ...
│ └── (80 icons total)
├── favicon/
│ ├── favicon.ico # Multi-size (16, 32, 48)
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-48x48.png
│ ├── favicon-192x192.png
│ └── apple-touch-icon.png # 180x180
└── icons.json # PWA manifest-ready
Ready to use in your manifest.json:
{
"icons": [
{
"src": "ios/512.png",
"sizes": "512x512"
},
{
"src": "android/android-launchericon-192-192.png",
"sizes": "192x192"
}
]
}Sizes: 16, 20, 29, 32, 40, 50, 57, 58, 60, 64, 72, 76, 80, 87, 100, 114, 120, 128, 144, 152, 167, 180, 192, 256, 512, 1024
Covers: iPhone, iPad, App Store, Spotlight, Settings
| Density | Size |
|---|---|
| mdpi | 48×48 |
| hdpi | 72×72 |
| xhdpi | 96×96 |
| xxhdpi | 144×144 |
| xxxhdpi | 192×192 |
| Play Store | 512×512 |
| Type | Scales | Count |
|---|---|---|
| SmallTile | 100, 125, 150, 200, 400 | 5 |
| Square150x150Logo | 100, 125, 150, 200, 400 | 5 |
| Wide310x150Logo | 100, 125, 150, 200, 400 | 5 |
| LargeTile | 100, 125, 150, 200, 400 | 5 |
| Square44x44Logo | 100, 125, 150, 200, 400 | 5 |
| StoreLogo | 100, 125, 150, 200, 400 | 5 |
| SplashScreen | 100, 125, 150, 200, 400 | 5 |
| Square44x44Logo.targetsize | 16-256 (15 sizes) | 15 |
| Square44x44Logo.altform-unplated | 16-256 (15 sizes) | 15 |
| Square44x44Logo.altform-lightunplated | 16-256 (15 sizes) | 15 |
| File | Size | Purpose |
|---|---|---|
| favicon.ico | 16, 32, 48 | Classic favicon (multi-size ICO) |
| favicon-16x16.png | 16×16 | Modern browsers |
| favicon-32x32.png | 32×32 | Modern browsers, HiDPI |
| favicon-48x48.png | 48×48 | Windows site icons |
| favicon-192x192.png | 192×192 | Android Chrome |
| apple-touch-icon.png | 180×180 | iOS home screen |
- 118 icons in ~0.7 seconds (all platforms including favicon)
- 10 concurrent operations via p-limit
- Source image processed once, buffer reused
- Sharp (libvips) for native-speed processing
| Metric | Coverage |
|---|---|
| Functions | 100% |
| Lines | 99.33% |
| Tests | 92 |
bun test --coverage- Bun v1.0.0+
- Source image: Square, minimum 256×256px (512×512+ recommended)
bun run start # Run CLI
bun run dev # Run with watch mode
bun run build # Compile to single binary
bun run typecheck # TypeScript checkCreate a standalone executable:
bun run build
./dist/pwa-icons -i logo.png -y| Package | Purpose |
|---|---|
| sharp | Image processing (libvips) |
| @clack/prompts | Beautiful interactive prompts |
| commander | CLI argument parsing |
| chalk | Terminal styling |
| p-limit | Concurrency control |
If you need features like iOS device-specific splash screens, dark mode splash screens, maskable icons, or HTML/CSS input, check out pwa-asset-generator — it uses Puppeteer/Chromium for browser-based rendering.
This package (pwa-icons) is a lightweight, faster alternative using Sharp/libvips for most common use cases.
MIT