@maccesar/titools 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/purgetss/SKILL.md +36 -0
- package/skills/purgetss/references/EXAMPLES.md +86 -24
- package/skills/purgetss/references/app-branding.md +554 -0
- package/skills/purgetss/references/appearance-module.md +161 -0
- package/skills/purgetss/references/apply-directive.md +87 -31
- package/skills/purgetss/references/arbitrary-values.md +4 -0
- package/skills/purgetss/references/class-categories.md +10 -7
- package/skills/purgetss/references/class-index.md +25 -18
- package/skills/purgetss/references/cli-commands.md +309 -8
- package/skills/purgetss/references/configurable-properties.md +11 -7
- package/skills/purgetss/references/custom-rules.md +7 -3
- package/skills/purgetss/references/customization-deep-dive.md +73 -4
- package/skills/purgetss/references/dynamic-component-creation.md +29 -14
- package/skills/purgetss/references/grid-layout.md +20 -8
- package/skills/purgetss/references/icon-fonts.md +4 -0
- package/skills/purgetss/references/installation-setup.md +3 -8
- package/skills/purgetss/references/ios-large-titles.md +141 -0
- package/skills/purgetss/references/migration-guide.md +162 -25
- package/skills/purgetss/references/multi-density-images.md +363 -0
- package/skills/purgetss/references/opacity-modifier.md +4 -0
- package/skills/purgetss/references/performance-tips.md +5 -0
- package/skills/purgetss/references/platform-modifiers.md +4 -0
- package/skills/purgetss/references/semantic-colors.md +386 -0
- package/skills/purgetss/references/smart-mappings.md +50 -28
- package/skills/purgetss/references/tikit-components.md +3 -1
- package/skills/purgetss/references/titanium-resets.md +46 -15
- package/skills/purgetss/references/ui-ux-design.md +32 -6
- package/skills/purgetss/references/values-and-units.md +120 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# App Icons & Branding
|
|
2
|
+
|
|
3
|
+
The `purgetss brand` command (introduced in PurgeTSS v7.6.0, restructured in v7.7.0) generates the complete Titanium branding set from a single SVG or PNG logo — with optional Android-specific overrides when you need them: launcher icons across every Android density, the adaptive-icon trio (foreground + background + monochrome), iOS 18+ Dark and Tinted variants, marketplace artwork, and optional notification/splash icons. Alloy and Classic layouts are auto-detected.
|
|
4
|
+
|
|
5
|
+
For the terse flag reference, see the [`brand` command reference](./cli-commands.md#brand-command). For sibling UI assets, see [Multi-Density Images](./multi-density-images.md).
|
|
6
|
+
|
|
7
|
+
> **INFO**
|
|
8
|
+
>
|
|
9
|
+
> The `brand` command at a glance
|
|
10
|
+
> `purgetss brand` turns one logo into every asset a Titanium app needs to ship — launcher icons, adaptive icons, iOS 18+ Dark/Tinted variants, marketplace artwork, and optional notification/splash icons. Works on both Alloy and Classic projects.
|
|
11
|
+
|
|
12
|
+
## Quick start
|
|
13
|
+
|
|
14
|
+
Drop a logo file into `purgetss/brand/`, then run the command. That's the whole workflow.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
mkdir -p purgetss/brand # if the folder doesn't exist yet
|
|
18
|
+
cp docs/my-logo.svg purgetss/brand/logo.svg
|
|
19
|
+
|
|
20
|
+
purgetss brand
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
On a first run the command:
|
|
24
|
+
|
|
25
|
+
1. Creates the `brand:` section in `purgetss/config.cjs` with sensible defaults (if missing).
|
|
26
|
+
2. Generates every branding file directly into the project (in-place).
|
|
27
|
+
3. Prints a compact summary of what was written.
|
|
28
|
+
|
|
29
|
+
Pass `--dry-run` to preview without writing any files:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
purgetss brand --dry-run
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## The `purgetss/brand/` convention
|
|
36
|
+
|
|
37
|
+
`init` creates `purgetss/brand/` (alongside `fonts/` and `images/`) so the folder is already there the first time you look for it, even before you've dropped in a logo.
|
|
38
|
+
|
|
39
|
+
PurgeTSS auto-discovers logo files under this folder, the same way `purgetss/fonts/` works for fonts. Drop files with these names and you're done — no flags, no config:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
purgetss/brand/
|
|
43
|
+
├── logo.svg required — main logo (or logo.png)
|
|
44
|
+
├── logo-icon.svg optional — square Android launcher mark
|
|
45
|
+
├── logo-mono.svg optional — monochrome layer + notifications
|
|
46
|
+
├── logo-dark.svg optional — iOS 18+ dark variant
|
|
47
|
+
├── logo-splash.svg optional — Android 12+ splash icon override
|
|
48
|
+
└── logo-tinted.svg optional — iOS 18+ tinted variant
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Only `logo.svg` (or `logo.png`) is required. Everything else is **opt-in refinement**:
|
|
52
|
+
|
|
53
|
+
| File | Required? | What it's for | Fallback when omitted |
|
|
54
|
+
| --- | --- | --- | --- |
|
|
55
|
+
| `logo.svg` / `logo.png` | **Required** | Main colored logo. Feeds every density and variant. | — |
|
|
56
|
+
| `logo-icon.svg` / `.png` | Optional | Square Android launcher mark — use when `logo.svg` is a wide wordmark or non-square lockup. | Main logo is reused for Android launcher icons. |
|
|
57
|
+
| `logo-mono.svg` / `.png` | Optional | Android adaptive monochrome layer (themed icons on Android 13+) and notification icons. | Main logo is whitened automatically. |
|
|
58
|
+
| `logo-splash.svg` / `.png` | Optional | Android 12+ `splash_icon.png` artwork (only used when `--splash` / `android.splash: true`). | Falls back to the launcher artwork. |
|
|
59
|
+
| `logo-dark.svg` / `.png` | Optional | iOS 18+ Dark appearance variant. | Main logo on a transparent background (Apple HIG default). |
|
|
60
|
+
| `logo-tinted.svg` / `.png` | Optional | iOS 18+ Tinted appearance variant. | Grayscale of the main logo on black. |
|
|
61
|
+
|
|
62
|
+
Provide a dedicated `logo-icon` when the main logo is a horizontal wordmark, a vertical lockup, or anything else that looks fine in a 1024×1024 branding canvas but feels cramped inside an Android launcher mask.
|
|
63
|
+
|
|
64
|
+
Provide a dedicated `logo-mono` when the colored logo has detail that would collapse into a featureless blob under naive whitening (e.g. a painter's palette with colored dots — the monochrome variant should have cutouts instead).
|
|
65
|
+
|
|
66
|
+
Provide a dedicated `logo-splash` when the Android 12+ splash should use a different composition than the launcher icon. PurgeTSS generates the file, but Titanium still needs a custom Android splash theme if you want the system splash to use it instead of `ic_launcher`.
|
|
67
|
+
|
|
68
|
+
Provide a dedicated `logo-dark` when dark-mode brand guidelines use a different lockup or color treatment; provide `logo-tinted` when you want a pre-simplified silhouette that tints better than a naive grayscale of the colored version.
|
|
69
|
+
|
|
70
|
+
> **INFO**
|
|
71
|
+
>
|
|
72
|
+
> Prefer SVG for the master
|
|
73
|
+
> SVG scales losslessly to every density Sharp needs to emit. A single `logo.svg` rasterizes perfectly at every `res-*dpi` output. PNG masters should be at least **1024×1024** to avoid upscaling artifacts.
|
|
74
|
+
|
|
75
|
+
### Overriding auto-discovery
|
|
76
|
+
|
|
77
|
+
You can also pass a path directly or point to a logo from the config. Useful when your masters live in `docs/` or another workflow folder:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
purgetss brand ./docs/snap-logo.svg
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or in `purgetss/config.cjs`:
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
brand: {
|
|
87
|
+
logos: {
|
|
88
|
+
primary: './docs/snap-logo.svg',
|
|
89
|
+
androidLauncher: './docs/snap-app-icon.svg',
|
|
90
|
+
monochrome: './docs/snap-logo-mono.svg'
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Precedence: **CLI flags win over config values, and config values win over auto-discovery.**
|
|
96
|
+
|
|
97
|
+
## The `brand:` config section (v7.7.0 grouped structure)
|
|
98
|
+
|
|
99
|
+
On the first run, `purgetss brand` injects a `brand:` block into your existing `purgetss/config.cjs` (between `purge:` and `theme:`) with these defaults. The structure is grouped by purpose:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
brand: {
|
|
103
|
+
logos: {
|
|
104
|
+
// Optional overrides. If omitted, PurgeTSS auto-discovers files from purgetss/brand/:
|
|
105
|
+
// primary: './docs/logo.svg',
|
|
106
|
+
// androidLauncher: './docs/app-icon.svg',
|
|
107
|
+
// androidSplash: './docs/splash.svg',
|
|
108
|
+
// monochrome: './docs/logo-mono.svg',
|
|
109
|
+
// iosDark: './docs/logo-dark.svg',
|
|
110
|
+
// iosTinted: './docs/logo-tinted.svg'
|
|
111
|
+
},
|
|
112
|
+
padding: {
|
|
113
|
+
ios: '4%', // iOS aesthetic padding. Range 2-8%. No launcher mask.
|
|
114
|
+
androidLegacy: '10%', // legacy ic_launcher.png padding %
|
|
115
|
+
androidAdaptive: '19%' // adaptive icon safe-zone %. Spec floor 19.44%.
|
|
116
|
+
},
|
|
117
|
+
android: {
|
|
118
|
+
splash: false, // also generate splash_icon.png × 5
|
|
119
|
+
notification: false // also generate ic_stat_notify.png × 5
|
|
120
|
+
},
|
|
121
|
+
colors: {
|
|
122
|
+
background: '#FFFFFF' // Android adaptive bg + iOS/marketplace flatten
|
|
123
|
+
},
|
|
124
|
+
// Optional iOS overrides:
|
|
125
|
+
// ios: {
|
|
126
|
+
// dark: false, // skip DefaultIcon-Dark.png
|
|
127
|
+
// tinted: false, // skip DefaultIcon-Tinted.png
|
|
128
|
+
// darkBackground: '#111' // opaque dark bg for DefaultIcon-Dark.png (null = transparent per Apple HIG)
|
|
129
|
+
// },
|
|
130
|
+
confirmOverwrites: true // prompt before overwriting files (set false to skip)
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The recommended workflow is convention-first: drop files in `purgetss/brand/`, let auto-discovery pick them up, and only set `brand.logos.*` when you have a persistent override. CLI flags still win for one-off runs.
|
|
135
|
+
|
|
136
|
+
### `brand.logos`
|
|
137
|
+
|
|
138
|
+
All `logos.*` keys are optional path overrides. If you omit them, PurgeTSS auto-discovers files from `purgetss/brand/`.
|
|
139
|
+
|
|
140
|
+
| Key | Auto-discovers | Purpose |
|
|
141
|
+
| --- | --- | --- |
|
|
142
|
+
| `logos.primary` | `purgetss/brand/logo.svg` | Main brand source. |
|
|
143
|
+
| `logos.androidLauncher` | `purgetss/brand/logo-icon.svg` | Square Android launcher mark — use when the main logo is a wordmark. |
|
|
144
|
+
| `logos.androidSplash` | `purgetss/brand/logo-splash.svg` | Android 12+ splash artwork. |
|
|
145
|
+
| `logos.monochrome` | `purgetss/brand/logo-mono.svg` | Android themed icons + notification icons. |
|
|
146
|
+
| `logos.iosDark` | `purgetss/brand/logo-dark.svg` | iOS dark variant. |
|
|
147
|
+
| `logos.iosTinted` | `purgetss/brand/logo-tinted.svg` | iOS tinted variant. |
|
|
148
|
+
|
|
149
|
+
### `brand.padding`
|
|
150
|
+
|
|
151
|
+
All padding values accept either numbers or percentage strings like `'19%'`.
|
|
152
|
+
|
|
153
|
+
| Key | Default | Purpose |
|
|
154
|
+
| --- | --- | --- |
|
|
155
|
+
| `padding.ios` | `'4%'` | Visual inset for `DefaultIcon-ios.png`, `DefaultIcon-Dark.png`, `DefaultIcon-Tinted.png`, marketplace artwork. |
|
|
156
|
+
| `padding.androidLegacy` | `'10%'` | Visual inset for legacy `ic_launcher.png`. |
|
|
157
|
+
| `padding.androidAdaptive` | `'19%'` | Visual inset for adaptive Android foreground (`ic_launcher_foreground.png`). Adjust this first when icons look cropped inside launcher masks. |
|
|
158
|
+
|
|
159
|
+
### `brand.android`
|
|
160
|
+
|
|
161
|
+
| Key | Default | Purpose |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `android.splash` | `false` | When `true`, also generates `drawable-*/splash_icon.png`. |
|
|
164
|
+
| `android.notification` | `false` | When `true`, also generates `drawable-*/ic_stat_notify.png`. |
|
|
165
|
+
|
|
166
|
+
### `brand.ios` (optional)
|
|
167
|
+
|
|
168
|
+
If omitted, PurgeTSS behaves as if `ios.dark = true`, `ios.tinted = true`, `ios.darkBackground = null`.
|
|
169
|
+
|
|
170
|
+
| Key | Default | Purpose |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| `ios.dark` | `true` | Set to `false` to skip `DefaultIcon-Dark.png`. |
|
|
173
|
+
| `ios.tinted` | `true` | Set to `false` to skip `DefaultIcon-Tinted.png`. |
|
|
174
|
+
| `ios.darkBackground` | `null` | When `null`, `DefaultIcon-Dark.png` stays transparent per Apple HIG. Set a hex to bake in an opaque dark background. |
|
|
175
|
+
|
|
176
|
+
### `brand.colors`
|
|
177
|
+
|
|
178
|
+
| Key | Default | Purpose |
|
|
179
|
+
| --- | --- | --- |
|
|
180
|
+
| `colors.background` | `'#FFFFFF'` | Triple-purpose: Android adaptive background layer, iOS alpha flatten for `DefaultIcon-ios.png`, marketplace flatten for `iTunesConnect.png` / `MarketplaceArtwork.png` when overridden. |
|
|
181
|
+
|
|
182
|
+
### `brand.confirmOverwrites`
|
|
183
|
+
|
|
184
|
+
| Key | Default | Purpose |
|
|
185
|
+
| --- | --- | --- |
|
|
186
|
+
| `confirmOverwrites` | `true` | When `false`, the `[y/N/a]` prompt is skipped. |
|
|
187
|
+
|
|
188
|
+
## Overwrite confirmation
|
|
189
|
+
|
|
190
|
+
`brand` writes directly into the project, so it asks before overwriting anything:
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
In-place mode will OVERWRITE files in <project>. Commit first if you want a rollback.
|
|
194
|
+
Continue? [y/N/a]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- `y` / `yes` — write this time
|
|
198
|
+
- `N` / `no` / `Enter` — abort (nothing is written)
|
|
199
|
+
- `a` / `always` — write, then add `confirmOverwrites: false` to the `brand:` section of `config.cjs` so the prompt stays quiet on future runs
|
|
200
|
+
|
|
201
|
+
The prompt is skipped automatically when:
|
|
202
|
+
|
|
203
|
+
- `stdin` is not a TTY (the `alloy.jmk` hook, CI, a pipe)
|
|
204
|
+
- you pass `-y` / `--yes` — one-shot bypass
|
|
205
|
+
- `PURGETSS_YES=1` is set in the environment — lasts the whole shell session
|
|
206
|
+
- `confirmOverwrites: false` is already in the `brand:` config
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
purgetss brand -y # skip prompt once
|
|
210
|
+
PURGETSS_YES=1 purgetss brand # skip for the whole session
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## What gets generated
|
|
214
|
+
|
|
215
|
+
The output is automatically routed to the right directory for your project layout.
|
|
216
|
+
|
|
217
|
+
**Alloy layout:**
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
<project>/
|
|
221
|
+
├── DefaultIcon.png ← 1024×1024, universal fallback (Android-safe padding)
|
|
222
|
+
├── DefaultIcon-ios.png ← 1024×1024, iOS flattened on bgColor
|
|
223
|
+
├── DefaultIcon-Dark.png ← 1024×1024, iOS 18+ dark (transparent per Apple HIG)
|
|
224
|
+
├── DefaultIcon-Tinted.png ← 1024×1024, iOS 18+ tinted (grayscale on black)
|
|
225
|
+
├── iTunesConnect.png ← 1024×1024, App Store submission
|
|
226
|
+
├── MarketplaceArtwork.png ← 512×512, Google Play submission
|
|
227
|
+
└── app/
|
|
228
|
+
└── assets/android/
|
|
229
|
+
├── default.png ← legacy Titanium Android splash fallback (v7.7.0)
|
|
230
|
+
└── res/
|
|
231
|
+
├── mipmap-mdpi/ ← 108×108 foreground + background + monochrome + legacy
|
|
232
|
+
├── mipmap-hdpi/ ← 162×162
|
|
233
|
+
├── mipmap-xhdpi/ ← 216×216
|
|
234
|
+
├── mipmap-xxhdpi/ ← 324×324
|
|
235
|
+
├── mipmap-xxxhdpi/ ← 432×432
|
|
236
|
+
├── drawable-*/ ← optional splash_icon.png when --splash is enabled
|
|
237
|
+
└── mipmap-anydpi-v26/
|
|
238
|
+
└── ic_launcher.xml ← adaptive-icon binder
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Classic layout:**
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
<project>/
|
|
245
|
+
├── DefaultIcon.png DefaultIcon-ios.png ... ← same root-level files as Alloy
|
|
246
|
+
├── Resources/
|
|
247
|
+
│ └── android/default.png ← legacy Titanium Android splash fallback (v7.7.0)
|
|
248
|
+
└── platform/
|
|
249
|
+
└── android/res/
|
|
250
|
+
├── mipmap-*/ ← same 5 densities as Alloy
|
|
251
|
+
├── drawable-*/ ← optional splash_icon.png when --splash is enabled
|
|
252
|
+
└── mipmap-anydpi-v26/ic_launcher.xml
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The Android outputs are related, but they are not interchangeable:
|
|
256
|
+
|
|
257
|
+
- `ic_launcher*` drives the app icon, and by default also feeds the Android 12+ system splash
|
|
258
|
+
- `splash_icon.png` is only generated when you ask for it with `--splash`
|
|
259
|
+
- `default.png` is the older Titanium Android splash fallback (regenerated since v7.7.0)
|
|
260
|
+
|
|
261
|
+
## Android dark mode
|
|
262
|
+
|
|
263
|
+
> **INFO**
|
|
264
|
+
>
|
|
265
|
+
> No separate "dark icon" file on Android
|
|
266
|
+
> Unlike iOS 18+, Android has no dedicated dark-mode icon file. Instead, Android 13+ uses the **monochrome layer** of the adaptive icon and tints it based on the user's wallpaper + theme.
|
|
267
|
+
>
|
|
268
|
+
> The `brand` command generates `ic_launcher_monochrome.png` at every density by default — you don't need any extra flags to get themed icon support.
|
|
269
|
+
|
|
270
|
+
If you want to provide a dedicated silhouette (recommended for detailed logos):
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
cp docs/my-logo-mono.svg purgetss/brand/logo-mono.svg
|
|
274
|
+
purgetss brand
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The monochrome layer is pure white (`RGB 255,255,255`) with alpha preserved. Android applies the user's tint on top at render time.
|
|
278
|
+
|
|
279
|
+
## Android 12+ splash artwork
|
|
280
|
+
|
|
281
|
+
If you pass `--splash`, PurgeTSS generates `drawable-*/splash_icon.png` across Android densities.
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
purgetss brand --splash
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
If you want that artwork to differ from the launcher icon, provide `logo-splash.svg` or set `brand.logos.androidSplash`:
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
brand: {
|
|
291
|
+
android: {
|
|
292
|
+
splash: true
|
|
293
|
+
},
|
|
294
|
+
logos: {
|
|
295
|
+
androidSplash: './docs/snap-splash-mark.svg'
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
> **INFO**
|
|
301
|
+
>
|
|
302
|
+
> Generating `splash_icon.png` does not automatically switch Titanium to use it for the Android 12+ system splash. Titanium still needs a custom splash theme that points `android:windowSplashScreenAnimatedIcon` to `@drawable/splash_icon`. If you do nothing, Android keeps using `ic_launcher`.
|
|
303
|
+
|
|
304
|
+
## Android legacy splash fallback
|
|
305
|
+
|
|
306
|
+
Since v7.7.0, PurgeTSS regenerates `app/assets/android/default.png` in Alloy projects and `Resources/android/default.png` in Classic projects.
|
|
307
|
+
|
|
308
|
+
That file still matters as a fallback on older Titanium Android splash paths, which is why `cleanup-legacy` no longer removes it.
|
|
309
|
+
|
|
310
|
+
## iOS 18+ Dark and Tinted variants
|
|
311
|
+
|
|
312
|
+
iOS 18 added two appearance variants on top of the standard app icon: **Dark** (for the dark appearance of the Home Screen) and **Tinted** (for the user-accent-colored mode).
|
|
313
|
+
|
|
314
|
+
The `brand` command generates both by default:
|
|
315
|
+
|
|
316
|
+
- **`DefaultIcon-Dark.png`**: 1024×1024, **transparent by default** per Apple HIG. The system paints its own dark gradient behind the icon at render time. Override with `--dark-bg-color <hex>` to bake in an opaque dark tint instead.
|
|
317
|
+
- **`DefaultIcon-Tinted.png`**: 1024×1024, **grayscale on black (`#000000`)** per Apple HIG. iOS composites its own gradient background and multiplies the luminance by the user-selected accent color at render time.
|
|
318
|
+
|
|
319
|
+
### Skipping Dark or Tinted
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
purgetss brand --no-dark
|
|
323
|
+
purgetss brand --no-tinted
|
|
324
|
+
purgetss brand --no-dark --no-tinted
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Titanium SDK wiring status
|
|
328
|
+
|
|
329
|
+
> **WARNING**
|
|
330
|
+
>
|
|
331
|
+
> Upstream work in progress
|
|
332
|
+
> As of April 2026, Titanium SDK picks up `DefaultIcon-ios.png` automatically but does **not** yet wire `DefaultIcon-Dark.png` / `DefaultIcon-Tinted.png` into the generated iOS appiconset. Upstream tracking: [tidev/titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122).
|
|
333
|
+
>
|
|
334
|
+
> Until that PR lands, after your first iOS build you may need to add the two PNGs manually into `build/iphone/Assets.xcassets/AppIcon.appiconset/` in Xcode (via the "Appearance" column in the asset catalog editor). Once #14122 merges, the command becomes fully end-to-end.
|
|
335
|
+
|
|
336
|
+
## Brand color
|
|
337
|
+
|
|
338
|
+
The `--bg-color` flag (or `brand.bgColor` in config) controls three things at once:
|
|
339
|
+
|
|
340
|
+
1. The **Android adaptive background layer**: a solid color that fills the full 108dp canvas behind your logo.
|
|
341
|
+
2. The **iOS alpha flatten** for `DefaultIcon-ios.png`. Apple rejects transparent App Store icons, so the logo is flattened on this color.
|
|
342
|
+
3. The **marketplace flatten** for `iTunesConnect.png` and `MarketplaceArtwork.png` when you pass a non-default value explicitly.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
purgetss brand --bg-color "#0B1326"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
If you never pass the flag, background stays `#FFFFFF` and the marketplace artwork keeps its alpha channel (matches Titanium's default).
|
|
349
|
+
|
|
350
|
+
## Padding guidance
|
|
351
|
+
|
|
352
|
+
Since v7.7.0, PurgeTSS treats Android adaptive and Android legacy launcher icons as two related but different cases:
|
|
353
|
+
|
|
354
|
+
- `brand.padding.androidAdaptive` or `--android-adaptive-padding` for the adaptive foreground
|
|
355
|
+
- `brand.padding.androidLegacy` or `--android-legacy-padding` for `ic_launcher.png`
|
|
356
|
+
- `--padding` is a one-shot **shortcut** that sets both Android paddings to the same value for one run
|
|
357
|
+
|
|
358
|
+
The adaptive default is `19%`, which stays close to the Android safe-zone. The legacy default is `10%`, so the flat `ic_launcher.png` can keep a little more visual weight.
|
|
359
|
+
|
|
360
|
+
### Adaptive icon padding
|
|
361
|
+
|
|
362
|
+
| Padding | Logo fill | When to use |
|
|
363
|
+
| ------- | --------- | ------------------------------------------------------------------------------------------------------ |
|
|
364
|
+
| `15%` | 70% | Aggressive. Better for square symbols with lots of built-in breathing room. |
|
|
365
|
+
| `18%` | 64% | Defensive: for intricate logos, fine serifs, multi-element designs. |
|
|
366
|
+
| `19%` | 62% | **Default**. Close to the Android safe-zone and safer for adaptive masks. |
|
|
367
|
+
| `20%` | 60% | Conservative, spec-compliant. Safe on every launcher, including aggressive masks. |
|
|
368
|
+
|
|
369
|
+
A useful visual check is the "corners" heuristic: imagine a circle inscribed in your 1024×1024 canvas with the given padding. If your logo's outermost corners fit inside that circle, you're safe on circular launchers (Pixel default, Oppo Android 15). If they poke out, they'll be clipped.
|
|
370
|
+
|
|
371
|
+
The official Android spec floor is `19.44%` (108dp canvas, 66dp inscribed safe-zone circle). That is the theoretical worst-case for aggressive adaptive masks, which is why the adaptive default now sits close to it.
|
|
372
|
+
|
|
373
|
+
### Legacy icon padding
|
|
374
|
+
|
|
375
|
+
Legacy `ic_launcher.png` does not go through the same adaptive mask, so it can usually run tighter. That is why the default for `brand.padding.androidLegacy` is `10%`.
|
|
376
|
+
|
|
377
|
+
### iOS padding
|
|
378
|
+
|
|
379
|
+
`--ios-padding` is a separate lever — iOS has no launcher mask, so the range is different:
|
|
380
|
+
|
|
381
|
+
| iOS padding | When to use |
|
|
382
|
+
| --- | --- |
|
|
383
|
+
| `2%` | Bold, edge-to-edge logos. |
|
|
384
|
+
| `4%` | **Default**. Balanced aesthetic. |
|
|
385
|
+
| `8%` | Conservative, generous whitespace around the mark. |
|
|
386
|
+
|
|
387
|
+
## Cleanup legacy branding artifacts
|
|
388
|
+
|
|
389
|
+
Projects that predate Android adaptive icons (API 26+) or modern iOS launch storyboards often accumulate obsolete assets: `res-long-*/res-notlong-*` qualifiers dead since Android 3.0, legacy `Default-*.png` launch images ignored when the storyboard is enabled, pre-adaptive `appicon.png`, and so on.
|
|
390
|
+
|
|
391
|
+
The `--cleanup-legacy` flag removes them with context-aware safety rules: it reads `tiapp.xml` to decide what's safe to delete based on your project's configuration. Always preview first:
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
purgetss brand --cleanup-legacy --dry-run
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Review the output, then remove `--dry-run` to apply:
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
purgetss brand --cleanup-legacy
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Add `--aggressive` to also remove `ldpi` density folders (less than 1% of active Android devices globally in 2026):
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
purgetss brand --cleanup-legacy --aggressive
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
> **DANGER**
|
|
410
|
+
>
|
|
411
|
+
> Commit first
|
|
412
|
+
> `--cleanup-legacy` deletes files permanently. Commit your project to git before running without `--dry-run` so `git restore` is available as a rollback.
|
|
413
|
+
|
|
414
|
+
## Troubleshooting
|
|
415
|
+
|
|
416
|
+
### The icon looks cropped or cramped on my phone
|
|
417
|
+
|
|
418
|
+
Your adaptive foreground is probably landing too close to the launcher mask. Increase `--android-adaptive-padding`:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
purgetss brand --android-adaptive-padding 20
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Or set it in the config:
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
brand: {
|
|
428
|
+
padding: {
|
|
429
|
+
androidAdaptive: '20%'
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### The icon looks tiny / lost in the middle
|
|
435
|
+
|
|
436
|
+
Adaptive padding is probably too generous. Lower it:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
purgetss brand --android-adaptive-padding 17
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### The monochrome version looks like a white blob
|
|
443
|
+
|
|
444
|
+
Your colored logo likely has multi-color detail that doesn't survive a naive whitening. Provide a dedicated silhouette:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
cp docs/my-logo-mono.svg purgetss/brand/logo-mono.svg
|
|
448
|
+
purgetss brand
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### iOS rejects the app icon upload ("contains transparency")
|
|
452
|
+
|
|
453
|
+
That's Apple's rule: App Store icons must have no alpha channel. `DefaultIcon-ios.png` is always flattened on `bgColor` for that reason. If you edited the file manually and reintroduced alpha, re-run `purgetss brand` to regenerate.
|
|
454
|
+
|
|
455
|
+
### The dark variant doesn't show on my iPhone
|
|
456
|
+
|
|
457
|
+
Dark variants require iOS 18+ and Titanium SDK automatic wiring (tracked upstream in [titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122)). Until that PR merges, you may need to add `DefaultIcon-Dark.png` and `DefaultIcon-Tinted.png` manually into the Xcode appiconset after the first iOS build.
|
|
458
|
+
|
|
459
|
+
### I get "Input image exceeds pixel limit" on an SVG from Affinity / Illustrator
|
|
460
|
+
|
|
461
|
+
Affinity Designer and Adobe Illustrator often bake transforms into the exported SVG's `viewBox`, so the intrinsic dimensions end up at something absurd like `29559×13542 pt`. Rasterized at 1× density, that blows past Sharp's pixel limit and the command crashes.
|
|
462
|
+
|
|
463
|
+
PurgeTSS checks the `viewBox` on every SVG. When either side is over `4096 pt`, it prints a warning with the actual dimensions and switches to an adaptive density that caps the output pixel count regardless of input size. The warning tells you the source is oversized; the command still finishes.
|
|
464
|
+
|
|
465
|
+
If you want to clean up the source, re-export from the vector editor with a canvas-sized viewBox (`0 0 1024 1024`, for example). The rasterized output is identical either way, but a normalized viewBox keeps the SVG portable for other tools.
|
|
466
|
+
|
|
467
|
+
### I changed my bg color — do I need to regenerate the Android densities too?
|
|
468
|
+
|
|
469
|
+
Yes. `bgColor` bakes into every Android background layer and the iOS flatten. Re-run:
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
purgetss brand --bg-color "#NEW_COLOR"
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
All 5 Android densities, marketplace artwork, and iOS variants regenerate in one pass.
|
|
476
|
+
|
|
477
|
+
## Full flag reference
|
|
478
|
+
|
|
479
|
+
**Project & output**
|
|
480
|
+
|
|
481
|
+
| Flag | Purpose |
|
|
482
|
+
| --- | --- |
|
|
483
|
+
| `--project <path>` | Project root (defaults to cwd). |
|
|
484
|
+
| `--dry-run` | Preview what would be generated without writing any files. |
|
|
485
|
+
| `--output <dir>` | Stage into `<dir>` instead of writing in place. |
|
|
486
|
+
| `-y`, `--yes` | Skip the overwrite confirmation prompt for this invocation. |
|
|
487
|
+
|
|
488
|
+
**Visual customization**
|
|
489
|
+
|
|
490
|
+
| Flag | Purpose |
|
|
491
|
+
| --- | --- |
|
|
492
|
+
| `--bg-color <hex>` | Background color for Android adaptive + iOS/marketplace flatten. |
|
|
493
|
+
| `--padding <n>` | Shortcut: sets BOTH Android paddings to the same value for one run. |
|
|
494
|
+
| `--android-adaptive-padding <n>` | Adaptive icon safe-zone % (default `19`). |
|
|
495
|
+
| `--android-legacy-padding <n>` | Legacy `ic_launcher.png` padding % (default `10`). |
|
|
496
|
+
| `--ios-padding <n>` | iOS aesthetic padding % (range `2–8`, default `4`). |
|
|
497
|
+
|
|
498
|
+
**Optional asset types**
|
|
499
|
+
|
|
500
|
+
| Flag | Purpose |
|
|
501
|
+
| --- | --- |
|
|
502
|
+
| `--notification` | Also emit `ic_stat_notify.png × 5`. |
|
|
503
|
+
| `--splash` | Also emit `splash_icon.png × 5`. |
|
|
504
|
+
|
|
505
|
+
**Logo variants & overrides**
|
|
506
|
+
|
|
507
|
+
| Flag | Purpose |
|
|
508
|
+
| --- | --- |
|
|
509
|
+
| `--icon-logo <path>` | Override `purgetss/brand/logo-icon.{svg,png}` for Android launcher icons. |
|
|
510
|
+
| `--monochrome-logo <path>` | Override `purgetss/brand/logo-mono.{svg,png}`. |
|
|
511
|
+
| `--dark-logo <path>` | Override `purgetss/brand/logo-dark.{svg,png}`. |
|
|
512
|
+
| `--dark-bg-color <hex>` | Opaque dark bg for `DefaultIcon-Dark.png` (default: transparent per Apple HIG). |
|
|
513
|
+
| `--splash-logo <path>` | Override `purgetss/brand/logo-splash.{svg,png}` for Android 12+ splash artwork. |
|
|
514
|
+
| `--tinted-logo <path>` | Override `purgetss/brand/logo-tinted.{svg,png}`. |
|
|
515
|
+
| `--no-dark` | Skip `DefaultIcon-Dark.png`. |
|
|
516
|
+
| `--no-tinted` | Skip `DefaultIcon-Tinted.png`. |
|
|
517
|
+
|
|
518
|
+
**Legacy cleanup**
|
|
519
|
+
|
|
520
|
+
| Flag | Purpose |
|
|
521
|
+
| --- | --- |
|
|
522
|
+
| `--cleanup-legacy` | Remove obsolete branding artifacts (reads `tiapp.xml` for safety rules). Keeps `default.png` on purpose. |
|
|
523
|
+
| `--aggressive` | With `--cleanup-legacy`, also remove `ldpi` density folders. |
|
|
524
|
+
|
|
525
|
+
**Diagnostics**
|
|
526
|
+
|
|
527
|
+
| Flag | Purpose |
|
|
528
|
+
| --- | --- |
|
|
529
|
+
| `--notes` | Print full `tiapp.xml` snippets + padding tuning guide. |
|
|
530
|
+
| `--debug` | Print extra diagnostics. |
|
|
531
|
+
|
|
532
|
+
### Examples
|
|
533
|
+
|
|
534
|
+
```bash
|
|
535
|
+
purgetss brand # uses purgetss/brand/logo.svg + config
|
|
536
|
+
purgetss brand --bg-color "#0B1326" # override bg color
|
|
537
|
+
purgetss brand --icon-logo ./docs/app-icon.svg # dedicated square Android launcher mark
|
|
538
|
+
purgetss brand --splash --splash-logo ./docs/splash.svg # custom Android 12+ splash artwork
|
|
539
|
+
purgetss brand --notification --splash # add notification + splash
|
|
540
|
+
purgetss brand --no-tinted # skip iOS 18+ tinted variant
|
|
541
|
+
purgetss brand --dry-run # preview without writing
|
|
542
|
+
purgetss brand --cleanup-legacy --dry-run # preview legacy cleanup
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Community-Discovered Patterns
|
|
546
|
+
|
|
547
|
+
- **Titanium SDK wiring lag for iOS 18+ variants.** Titanium SDK currently wires `DefaultIcon-ios.png` into the generated appiconset automatically, but `DefaultIcon-Dark.png` and `DefaultIcon-Tinted.png` are not picked up yet. Until [tidev/titanium-sdk#14122](https://github.com/tidev/titanium-sdk/issues/14122) merges, the practical workaround is: run `ti build -p ios` once, then open `build/iphone/Assets.xcassets/AppIcon.appiconset/` in Xcode and drag the two PNGs into the "Appearance" column of the asset catalog editor. The generated PNGs are already named and sized correctly — no resizing needed.
|
|
548
|
+
- **Wordmark logos need a separate launcher mark.** When `logo.svg` is a wide wordmark or vertical lockup, it tends to look cramped inside Android launcher masks. Drop a square `logo-icon.svg` (or set `brand.logos.androidLauncher`) and the launcher icons get the dedicated mark while the rest of the brand set still uses the main logo. Same idea applies to Android 12+ splash with `logo-splash.svg`.
|
|
549
|
+
- **Three Android assets, three different jobs.** `ic_launcher*` drives the app icon and the default Android 12+ splash; `splash_icon.png` is generated only when you pass `--splash` and Titanium needs an explicit splash theme to actually use it; `default.png` is the older Titanium Android splash fallback (regenerated since v7.7.0, intentionally kept by `cleanup-legacy`). Knowing which file does what saves a lot of "but the icon didn't change" debugging.
|
|
550
|
+
|
|
551
|
+
## See also
|
|
552
|
+
|
|
553
|
+
- [`brand` command reference](./cli-commands.md#brand-command) — terse flag list.
|
|
554
|
+
- [Multi-Density Images](./multi-density-images.md) — sibling `images` command for UI assets.
|