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
| Family | Files |
|---|---|
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 |
| OHOS | startIcon.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:monochromeas 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 committedmipmap-anydpi-v26/ic_launcher.xml. - HarmonyOS layered icon:
layered_image.json+foreground.png/background.png(216 px) in both media dirs, withapp.json5/module.json5icon slots rewired to$media:layered_image(startWindowIconkeeps the flatstartIcon.png). - Icon Composer package (Xcode 26 Liquid Glass):
AppIcon.icon/—icon.json+ SVG layer assets split from the master’sday:layers (day:monochromeships as an asset for the Tinted appearance) — staged intoresource/icons/ios/andplatform/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).