diff --git a/Services/Website/README.md b/Services/Website/README.md index 5f85d3a..7e410c7 100644 --- a/Services/Website/README.md +++ b/Services/Website/README.md @@ -213,6 +213,27 @@ Preview the optimized output locally — requires only Docker and writes to the make ast-minify ``` +### Icons +All icons are renditions of the star mark in `icon.svg`, which is the canonical source — there is no external design file to regenerate from. + +| File | Size | Used by | Dark mode | +| --- | --- | --- | --- | +| `icon.svg` | vector | Tab icon in modern browsers (preferred over the ICO) | Adapts: an embedded `prefers-color-scheme` style flips the accent paths from `#000` to `#f3ecf5`. | +| `favicon.ico` | 32×32 | Tab icon in browsers without SVG favicon support (Safari) | Theme-neutral **by design**: it is the orange star *without* the accent paths, so one raster reads on both themes. Keep it accent-free when regenerating. | +| `icon-192.png`, `icon-512.png` | 192/512 | `site.webmanifest` install icons and splash screens | None (no platform mechanism); full artwork, light rendering, on a transparent background. | +| `apple-touch-icon.png` | 180×180 | iOS home-screen bookmarks | None (fetched once, outside any page context); full artwork, deliberately opaque — iOS fills transparent regions with black. | + +The landing page pairs the icons with two `theme-color` metas: `#0c0710` (media-qualified for dark, listed first — the first matching entry wins) and `#fafafa` as the fallback. + +The raster icons are committed binaries, regenerated from `icon.svg` on demand via a throwaway container (no local toolchain needed) — e.g. for the 512px rendition: +```sh +docker run --rm -v "$PWD/Resources/Static:/work" alpine sh -c ' + apk add --no-cache imagemagick librsvg oxipng && + magick -background none -density 256 /work/icon.svg -depth 8 PNG32:/work/icon-512.png && + oxipng --opt max --strip safe /work/icon-512.png' +``` +(`-density` scales the 192px viewBox: `96 × target ÷ 192`. For `favicon.ico`, rasterize a star-only copy of the SVG at 32px and pack it with `icotool -c --raw`.) + ### Required variables The Makefile and Compose files read these from a `.env` file (or the environment). Provide your own values — do **not** commit secrets. | Variable | Used for | diff --git a/Services/Website/Resources/Static/favicon.ico b/Services/Website/Resources/Static/favicon.ico index be74abd..2b5bcda 100644 Binary files a/Services/Website/Resources/Static/favicon.ico and b/Services/Website/Resources/Static/favicon.ico differ diff --git a/Services/Website/Resources/Static/icon-192.png b/Services/Website/Resources/Static/icon-192.png new file mode 100644 index 0000000..d94836c Binary files /dev/null and b/Services/Website/Resources/Static/icon-192.png differ diff --git a/Services/Website/Resources/Static/icon-512.png b/Services/Website/Resources/Static/icon-512.png new file mode 100644 index 0000000..6412cb0 Binary files /dev/null and b/Services/Website/Resources/Static/icon-512.png differ diff --git a/Services/Website/Resources/Static/icon.png b/Services/Website/Resources/Static/icon.png deleted file mode 100644 index 8a42581..0000000 Binary files a/Services/Website/Resources/Static/icon.png and /dev/null differ diff --git a/Services/Website/Resources/Static/icon.svg b/Services/Website/Resources/Static/icon.svg index f232922..68e7d38 100644 --- a/Services/Website/Resources/Static/icon.svg +++ b/Services/Website/Resources/Static/icon.svg @@ -1 +1 @@ - + diff --git a/Services/Website/Resources/Static/site.webmanifest b/Services/Website/Resources/Static/site.webmanifest index 222ae16..e5e517f 100644 --- a/Services/Website/Resources/Static/site.webmanifest +++ b/Services/Website/Resources/Static/site.webmanifest @@ -2,9 +2,13 @@ "short_name": "", "name": "", "icons": [{ - "src": "icon.png", + "src": "icon-192.png", "type": "image/png", "sizes": "192x192" + }, { + "src": "icon-512.png", + "type": "image/png", + "sizes": "512x512" }], "start_url": "/?utm_source=homescreen", "background_color": "#fafafa", diff --git a/Services/Website/Sources/Library/Internal/Enumerations/StaticFile.swift b/Services/Website/Sources/Library/Internal/Enumerations/StaticFile.swift index aed99f7..69afb22 100644 --- a/Services/Website/Sources/Library/Internal/Enumerations/StaticFile.swift +++ b/Services/Website/Sources/Library/Internal/Enumerations/StaticFile.swift @@ -10,8 +10,12 @@ enum StaticFile: CaseIterable, Sendable { case error /// The `favicon.ico` icon. case favicon - /// The `icon.png` and `icon.svg` icons. + /// The `icon.svg` icon. case icon + /// The `icon-192.png` icon for the web manifest. + case icon192 + /// The `icon-512.png` icon for the web manifest. + case icon512 /// The `css/index.css` stylesheet and `js/index.js` script for the landing page. case index /// The `robots.txt` crawler directives. @@ -57,12 +61,14 @@ extension StaticFile { /// The file extensions the file is available with. var fileExtensions: [Extension] { switch self { - case .appleTouchIcon: [.png] + case .appleTouchIcon, + .icon192, + .icon512: [.png] case .error, .index, .shared: [.css, .js] case .favicon: [.ico] - case .icon: [.png, .svg] + case .icon: [.svg] case .robots: [.txt] case .site: [.webmanifest] case .sitemap: [.xml] @@ -76,6 +82,8 @@ extension StaticFile { case .error: "error" case .favicon: "favicon" case .icon: "icon" + case .icon192: "icon-192" + case .icon512: "icon-512" case .index: "index" case .robots: "robots" case .shared: "shared" diff --git a/Services/Website/Sources/Library/Internal/Pages/IndexPage.swift b/Services/Website/Sources/Library/Internal/Pages/IndexPage.swift index 7f8bf19..6a9b6e2 100644 --- a/Services/Website/Sources/Library/Internal/Pages/IndexPage.swift +++ b/Services/Website/Sources/Library/Internal/Pages/IndexPage.swift @@ -74,6 +74,14 @@ struct IndexPage: HTMLDocument, Sendable { .rel("manifest"), .href(StaticFile.site.urlPath(for: .webmanifest)) ) + meta( + .name("theme-color"), + .content("#0c0710"), + .custom( + name: "media", + value: "(prefers-color-scheme: dark)" + ) + ) meta( .name("theme-color"), .content("#fafafa") diff --git a/Services/Website/Tests/Library/Cases/Internal/Enumerations/StaticFileTests.swift b/Services/Website/Tests/Library/Cases/Internal/Enumerations/StaticFileTests.swift index 4cb579f..24bde11 100644 --- a/Services/Website/Tests/Library/Cases/Internal/Enumerations/StaticFileTests.swift +++ b/Services/Website/Tests/Library/Cases/Internal/Enumerations/StaticFileTests.swift @@ -114,7 +114,7 @@ struct StaticFileTests { @Test func `all cases`() { - #expect(File.allCases.count == 9) + #expect(File.allCases.count == 11) } } @@ -159,7 +159,9 @@ private extension StaticFileTests { [.png], [.css, .js], [.ico], - [.png, .svg], + [.svg], + [.png], + [.png], [.css, .js], [.txt], [.css, .js], @@ -171,6 +173,8 @@ private extension StaticFileTests { "error", "favicon", "icon", + "icon-192", + "icon-512", "index", "robots", "shared", @@ -181,7 +185,9 @@ private extension StaticFileTests { ["apple-touch-icon.png"], ["css/error.css", "js/error.js"], ["favicon.ico"], - ["icon.png", "icon.svg"], + ["icon.svg"], + ["icon-192.png"], + ["icon-512.png"], ["css/index.css", "js/index.js"], ["robots.txt"], ["css/shared.css", "js/shared.js"], diff --git a/Services/Website/Tests/Library/Cases/Internal/Pages/IndexPageTests.swift b/Services/Website/Tests/Library/Cases/Internal/Pages/IndexPageTests.swift index a754d77..fc308d2 100644 --- a/Services/Website/Tests/Library/Cases/Internal/Pages/IndexPageTests.swift +++ b/Services/Website/Tests/Library/Cases/Internal/Pages/IndexPageTests.swift @@ -23,6 +23,7 @@ struct IndexPageTests { #expect(html.contains("/icon.svg")) #expect(html.contains("/apple-touch-icon.png")) #expect(html.contains("/site.webmanifest")) + #expect(html.contains(#"media="(prefers-color-scheme: dark)""#)) #expect(html.contains("Hello world!")) #expect(html.contains("/js/shared.js")) #expect(html.contains("/js/index.js"))