Created
March 20, 2026 23:39
-
-
Save leogdion/f9330d9f624c6b623306648bfe23c8f5 to your computer and use it in GitHub Desktop.
Export Icon Composer Icons for Press Kits and Web Sites
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # MonthBar Icon Exporter | |
| # Exports all app icon renditions from Resources/AppIcon.icon: | |
| # Marketing/Web/app-icon/ ← PNG + WebP at 1024px and 512px for all renditions | |
| # ← Favicons (180, 32, 16px) and OG image (1200×630) | |
| set -e | |
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | |
| # Constants | |
| ICON_COMPOSER="/Applications/Icon Composer.app" | |
| ICTOOL="$ICON_COMPOSER/Contents/Executables/ictool" | |
| ICON_SOURCE="$PROJECT_ROOT/Resources/AppIcon.icon" | |
| WEB_OUTPUT_DIR="$PROJECT_ROOT/Marketing/Web" | |
| ICON_OUTPUT_DIR="$WEB_OUTPUT_DIR/app-icon" | |
| # Tint colors for ictool (hue value 0.0–1.0) | |
| TINT_BLUE="0.60" # Brand blue #0088FF | |
| TINT_GREEN="0.50" # Progress green #34C759 | |
| TINT_STRENGTH="0.75" | |
| TINT_COLORS=("blue:$TINT_BLUE" "green:$TINT_GREEN") | |
| # Rendition → filename-suffix mapping | |
| RENDITIONS=( | |
| "Default:icon" | |
| "Dark:icon-dark" | |
| "ClearLight:icon-clear-light" | |
| "ClearDark:icon-clear-dark" | |
| "TintedLight:icon-tinted-light" | |
| "TintedDark:icon-tinted-dark" | |
| ) | |
| # Helper: run Python with Pillow via uv | |
| run_pillow() { | |
| mise exec -- uv run --with Pillow python3 "$@" | |
| } | |
| echo "MonthBar Icon Exporter" | |
| echo "" | |
| # Step 1: Validate | |
| echo "1. Validating..." | |
| if [ ! -f "$ICTOOL" ]; then | |
| echo " Error: ictool not found at $ICTOOL" | |
| echo " Ensure Icon Composer is installed at $ICON_COMPOSER" | |
| exit 1 | |
| fi | |
| if [ ! -d "$ICON_SOURCE" ]; then | |
| echo " Error: Icon source not found at $ICON_SOURCE" | |
| exit 1 | |
| fi | |
| echo " ictool and icon source found" | |
| # Step 2: Set up output directory | |
| echo "" | |
| echo "2. Setting up output directory..." | |
| rm -rf "$ICON_OUTPUT_DIR" | |
| mkdir -p "$ICON_OUTPUT_DIR" | |
| echo " $ICON_OUTPUT_DIR ready" | |
| # Step 3: Export icons (all 6 appearances at 1024px and 512px) | |
| echo "" | |
| echo "3. Exporting app icons..." | |
| export_icon() { | |
| local rendition="$1" suffix="$2" size="$3" | |
| local tint_args=("${@:4}") | |
| local png_file="$ICON_OUTPUT_DIR/${suffix}-${size}.png" | |
| local webp_file="$ICON_OUTPUT_DIR/${suffix}-${size}.webp" | |
| "$ICTOOL" "$ICON_SOURCE" --export-image --output-file "$png_file" \ | |
| --platform macOS --rendition "$rendition" \ | |
| --width "$size" --height "$size" --scale 1 "${tint_args[@]}" | |
| run_pillow -c " | |
| import sys | |
| from PIL import Image | |
| Image.open(sys.argv[1]).save(sys.argv[2], 'WEBP') | |
| " "$png_file" "$webp_file" | |
| echo " ${suffix}-${size}.png" | |
| echo " ${suffix}-${size}.webp" | |
| } | |
| for entry in "${RENDITIONS[@]}"; do | |
| rendition="${entry%%:*}" | |
| suffix="${entry##*:}" | |
| case "$rendition" in | |
| TintedLight|TintedDark) | |
| for tint_entry in "${TINT_COLORS[@]}"; do | |
| color_name="${tint_entry%%:*}" | |
| color_hue="${tint_entry##*:}" | |
| for size in 1024 512; do | |
| export_icon "$rendition" "${suffix}-${color_name}" "$size" \ | |
| --tint-color "$color_hue" --tint-strength "$TINT_STRENGTH" | |
| done | |
| done | |
| ;; | |
| *) | |
| for size in 1024 512; do | |
| export_icon "$rendition" "$suffix" "$size" | |
| done | |
| ;; | |
| esac | |
| done | |
| # Step 4: Generate favicons and OG image | |
| echo "" | |
| echo "4. Generating favicons and OG image..." | |
| ICON_1024="$ICON_OUTPUT_DIR/icon-1024.png" | |
| run_pillow -c " | |
| import sys | |
| from PIL import Image | |
| Image.open(sys.argv[1]).resize((180, 180), Image.LANCZOS).save(sys.argv[2]) | |
| " "$ICON_1024" "$ICON_OUTPUT_DIR/apple-touch-icon.png" | |
| echo " apple-touch-icon.png (180×180)" | |
| run_pillow -c " | |
| import sys | |
| from PIL import Image | |
| Image.open(sys.argv[1]).resize((32, 32), Image.LANCZOS).save(sys.argv[2]) | |
| " "$ICON_1024" "$ICON_OUTPUT_DIR/favicon-32x32.png" | |
| echo " favicon-32x32.png (32×32)" | |
| run_pillow -c " | |
| import sys | |
| from PIL import Image | |
| Image.open(sys.argv[1]).resize((16, 16), Image.LANCZOS).save(sys.argv[2]) | |
| " "$ICON_1024" "$ICON_OUTPUT_DIR/favicon-16x16.png" | |
| echo " favicon-16x16.png (16×16)" | |
| run_pillow -c " | |
| import sys | |
| from PIL import Image | |
| icon = Image.open(sys.argv[1]).resize((630, 630), Image.LANCZOS) | |
| og = Image.new('RGBA', (1200, 630), (0, 0, 0, 0)) | |
| og.paste(icon, ((1200 - 630) // 2, 0)) | |
| og.save(sys.argv[2]) | |
| og.save(sys.argv[3], 'WEBP') | |
| " "$ICON_1024" "$ICON_OUTPUT_DIR/og-image.png" "$ICON_OUTPUT_DIR/og-image.webp" | |
| echo " og-image.png (1200×630)" | |
| echo " og-image.webp (1200×630)" | |
| # Step 5: Summary | |
| echo "" | |
| echo "Complete! Generated files in Marketing/Web/app-icon/:" | |
| echo "" | |
| for entry in "${RENDITIONS[@]}"; do | |
| rendition="${entry%%:*}" | |
| suffix="${entry##*:}" | |
| case "$rendition" in | |
| TintedLight|TintedDark) | |
| for tint_entry in "${TINT_COLORS[@]}"; do | |
| color_name="${tint_entry%%:*}" | |
| echo " ${suffix}-${color_name}-1024.png (1024×1024)" | |
| echo " ${suffix}-${color_name}-1024.webp (1024×1024)" | |
| echo " ${suffix}-${color_name}-512.png (512×512)" | |
| echo " ${suffix}-${color_name}-512.webp (512×512)" | |
| done | |
| ;; | |
| *) | |
| echo " ${suffix}-1024.png (1024×1024)" | |
| echo " ${suffix}-1024.webp (1024×1024)" | |
| echo " ${suffix}-512.png (512×512)" | |
| echo " ${suffix}-512.webp (512×512)" | |
| ;; | |
| esac | |
| done | |
| echo "" | |
| echo " apple-touch-icon.png (180×180)" | |
| echo " favicon-32x32.png (32×32)" | |
| echo " favicon-16x16.png (16×16)" | |
| echo " og-image.png (1200×630)" | |
| echo " og-image.webp (1200×630)" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment