Icon Generation Targets
Regras de geração de variantes de ícone por plataforma (Android mipmaps, iOS app icons, Linux hicolor, macOS .icns, Windows .ico, web favicons, Store listing). Codificadas em `dev/kicon`. Nunca desenhar PNGs por densidade à mão — rodar `kicon generate` a partir do master SVG.
Spec — Icon generation targets (per-platform output rules)
Applicability
Every icon shipped by a Koder module. Source of truth for kicon generate (see dev/kicon). Human readers consult this when reasoning about why a specific file exists; machines consult the tool, which *ncodes these rules in code*— no drift is possible when apps use kicon.
Master SVG prerequisites
See meta/docs/stack/specs/icons/products.kmd. This spec assumes the master SVG is valid per that contract (viewBox 0 0 512 512, no background rect, content within inner 66 % circle, ≥ 4 % margin).
Target matrix
android
Covers both the legacy ic_launcher bitmaps (Android ≤ 7) and the adaptive-icon foreground for Android 8+.
| Path relative to module | Size | Source region | Alpha |
|---|---|---|---|
android/app/src/main/res/mipmap-mdpi/ic_launcher.png |
48×48 | full canvas | yes |
android/app/src/main/res/mipmap-hdpi/ic_launcher.png |
72×72 | full canvas | yes |
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png |
96×96 | full canvas | yes |
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png |
144×144 | full canvas | yes |
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png |
192×192 | full canvas | yes |
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png |
432×432 | full canvas (adaptive icon foreground) | yes |
Legacy bitmaps also emitted as ic_launcher_round.png with a soft mask (rounded-square corner mask applied at raster time).
linux
FreeDesktop hicolor icon theme.
| Path relative to module | Size |
|---|---|
linux/icon.png |
512×512 |
linux/share/icons/hicolor/16x16/apps/<slug>.png |
16×16 |
linux/share/icons/hicolor/24x24/apps/<slug>.png |
24×24 |
linux/share/icons/hicolor/32x32/apps/<slug>.png |
32×32 |
linux/share/icons/hicolor/48x48/apps/<slug>.png |
48×48 |
linux/share/icons/hicolor/64x64/apps/<slug>.png |
64×64 |
linux/share/icons/hicolor/128x128/apps/<slug>.png |
128×128 |
linux/share/icons/hicolor/256x256/apps/<slug>.png |
256×256 |
linux/share/icons/hicolor/512x512/apps/<slug>.png |
512×512 |
Slug = kicon.toml slug field or the module directory name.
web
| Path relative to module | Size | Alpha | Notes |
|---|---|---|---|
site/favicon-16.png |
16×16 | no | flattened against white; favicon.ico wrapper generated separately |
site/favicon-32.png |
32×32 | no | idem |
site/apple-touch-icon.png |
180×180 | no | iOS webapp icon — iOS ignores alpha |
site/maskable-512.png |
512×512 | yes | PWA maskable icon — full canvas inc. safe zone |
site/og-image.png |
1200×630 | yes | placeholder resize of master centered on transparent; proper OG images use a separate generator |
store
Koder Hub listing. Full-canvas display, no launcher cropping.
| Path relative to module | Size |
|---|---|
icon-256.png |
256×256 |
icon-512.png |
512×512 |
flutter-app
Embedded asset PNGs that a Flutter app loads via Image.asset('assets/icons/<slug>.png'). Distinct from the android target, which writes platformlauncher mipmaps. This is the inbundle asset every widget call site (AppBar logo, splash screen, settings header, system tray via tray_manager, Linux update notifications via local_notifier's AssetsLinuxIcon) renders with the app icon.
Detection: emitted only when <module>/app/pubspec.yaml exists OR <module>/app/assets/icons/ already exists. On non-Flutter modules the generator returns silently with zero emissions, so it can sit in the default target list without surprising side-effects.
Aliases: <module>/kicon.toml may declare additional names, byte- identical copies under each alias name. Used to keep widget call sites stable across rebrands (e.g. koder-hub.png → khub.png):
[targets.flutter-app]
aliases = ["koder-hub", "hub"]| Path relative to module | Size | Background |
|---|---|---|
app/assets/icons/<slug>.png |
512×512 | transparent |
app/assets/icons/<alias-1>.png … |
512×512 | transparent |
Spec authority: productsdevkicon#020. Origin: Hub v2.30.0/v2.30.1 shipped a new launcher with a stale AppBar logo because nobody re-generated the asset PNG (manual cp was the only path).
ios (v0.2 — deferred)
Full AppIcon.appiconset with 20+ sizes for iPhone / iPad / Spotlight / Notification / Settings / App Store (1024×1024). No alpha (iOS fills the background white or per-app tint).
macos (v0.2 — deferred)
.icns bundle with ic07 (128×128), ic08 (256×256), ic09 (512×512), ic10 (1024×1024), plus Retina variants ic11ic12ic13/ic14.
windows (v0.2 — deferred)
.ico file embedding 163248/256 PNG images.
Background handling per target
| Target | Transparent background? | Fallback for formats that disallow alpha |
|---|---|---|
| android | yes (all) | n/a — all Android formats support alpha |
| linux | yes | n/a |
| web | favicon: no; rest: yes | flatten onto white for favicon |
| store | yes | n/a |
| flutter-app | yes | n/a — Flutter widgets honour alpha |
| ios | no | flatten onto white |
| macos | yes | n/a |
| windows | yes (PNG inside .ico) | n/a |
Validation that must pass before generation
All of these run in kicon validate; kicon generate refuses to emit without a clean validation pass unless --force is set (CI only).
- *argin*(Error): rendered bbox leaves ≥ 4 % (20 px) on every side
of the 512 canvas. Matches
products.kmd§2 ("centralização óptica com tolerância ±4px"). This is the master-level margin contract. - *o background rect*(Error): no root-level opaque
<rect>thatfills the full canvas.
- *quare viewBox*(Error):
viewBox="0 0 N N"with identical widthand height.
- *o size attributes*(Warning): absence of
width=""andheight=""that force non-square rendering; SVG should scale to any target size. - *afe-zone*(Warning): rendered content bbox fits within the inner
66 % circle (
r = 512 × 0.33 = 169 pxfrom center). The Material Adaptive Icon safe zone is a target-level constraint, not a master-level one —kicon generateenforces it foric_launcher_foreground.png/ic_launcher_monochrome.pngby wrapping the master at 66.67% of the canvas (16.65% transparent margin on every side). Masters legitimately fill ~92 % of the canvas perproducts.kmd§2; the Warning surfaces masters whose content would still clip after wrapping (e.g. content centered well off the canvas center). Promoted to Error would block every existing product.
Canonical reference
products/dev/kicon/cmd/kicon/main.go— the Go reference implementation.- `productsdevkiconinternaltargets