App icons (day icon)

One master, every platform’s icon set, kept in sync. day icon renders the master into the resource/icons/ export tree and the committed platform/ copies each build consumes; day icon --check verifies nothing drifted (exit 5 — a CI gate beside the duty-matrix check).

The master

Discovery order: an explicit path argument, then resource/icons/icon.svg, resource/icons/day-icon.svg, resource/icons/icon.png.

An SVG master may mark top-level elements as semantic layers by id:

<rect id="day:background" …/>          <!-- the full-bleed backdrop -->
<g id="day:foreground"></g>           <!-- the motif; day:foreground-2 … for more layers -->
<g id="day:monochrome"></g>           <!-- reserved: themed/tinted modes (not yet consumed) -->
<g id="day:dark"></g>                 <!-- reserved: dark-mode variants (not yet consumed) -->

The composite (background + foregrounds) feeds every full-bleed output; the split layers feed Android’s adaptive icon (foreground tightened to its content box and centred in the 66/108 dp safe zone; background full-bleed). An unlayered SVG or a PNG master still produces the complete legacy set — the adaptive foreground is then the whole art in the safe zone over a derived background colour (the composite’s corner pixel; white when transparent).

Text must be outlined: text shaping is deliberately not compiled into day (<text> is a hard error naming the fix).

A reserved layer (day:monochrome, day:dark) may carry display="none" so plain SVG viewers show the master as it ships; the layer-only documents re-enable it. Generated masters do this.

Generate

day icon --generate writes a seeded pseudo-random layered master (background gradient + foreground motif + hidden monochrome silhouette) to resource/icons/icon.svg and renders every output from it. It refuses to replace an existing master unless --overwrite.

  • --seed <int|string> — reproduce a specific icon (a non-integer seed is hashed; the app-id convention below). Without it a fresh random seed is drawn — and always printed, so a liked icon can be regenerated.
  • --out <file.svg> — preview mode: write the master (plus a 512 px PNG beside it) to a path instead of the project, touching nothing else. No project needed; browse seeds with it.

day new app uses the same generator for every fresh scaffold, seeded by the app id — scaffolding the same id twice yields the same icon — with --icon-seed as the override.

The compositions are not free-form noise: a limited palette from the classic color-harmony schemes (analogous / complementary / split-complementary / triadic) with figure-ground contrast held by construction, one or two focal points in simple geometry within the masks’ safe zone, a subtle vertical background gradient, and symmetric / rotational / golden-section-balanced arrangements (day-vector/src/icongen.rs documents the sources). Generated monochrome layers stay inside the VectorDrawable subset, so Android’s themed icon ships as a true vector.

Outputs

FamilyFiles
png/day-icon-{16,32,64,128,256,512,1024}.png — favicons, catalogs, general use
macos/margin-composed squircle set (824 pt art on 1024, radius 184) -{16,32,128,256,512,1024}.png + day-icon.icns
ios/AppIcon-1024.png (opaque — App Store validation) + sync into platform/ios/…/AppIcon.appiconset/
android/adaptive ic_launcher_{foreground,background}.png (432), legacy 192, play-store-512.png + sync into platform/android/…/mipmap-xxxhdpi/
linux/day-icon-{48,128,256,512}.png (appstream-compose-safe sizes)
windows/multi-size day.ico (16/32/48/256, PNG-compressed) + day-icon-256.png
OHOSstartIcon.png sync into both platform/harmony/{entry,AppScope} media dirs

-p <target> limits generation to that target’s family. Everything renders in memory first, so --check compares bytes without touching the tree.

Modern formats

Beyond the legacy set, a layered SVG master also produces:

  • Android themed icon (Android 13): a monochrome drawable the system tints — day:monochrome as a VectorDrawable when it fits the subset, else the adaptive foreground’s alpha as a bitmap mask — plus an idempotent <monochrome> entry added to the committed mipmap-anydpi-v26/ic_launcher.xml.
  • HarmonyOS layered icon: layered_image.json + foreground.png/background.png (216 px) in both media dirs, with app.json5/module.json5 icon slots rewired to $media:layered_image (startWindowIcon keeps the flat startIcon.png).
  • Icon Composer package (Xcode 26 Liquid Glass): AppIcon.icon/icon.json + SVG layer assets split from the master’s day: layers (day:monochrome ships as an asset for the Tinted appearance) — staged into resource/icons/ios/ and platform/ios/. Open it in Icon Composer to tune materials, and point Xcode 26’s app-icon build setting at it; the appiconset remains the pre-26 fallback.

The lock

resource/icons/icons.lock.json records the generator (day-cli + engine version), the master’s digest, and a digest per output. Renders are byte-stable within one generator version; --check under a different version reports “regenerate with this day version” instead of false byte drift.

Engine

day-vector — resvg/usvg/tiny-skia with text shaping off, plus hand-rolled .ico/.icns writers. The same crate powers resource/vectors/ staging (docs/vectors.md).