feat(portal-shell): full favicon set + PWA manifest #84

Merged
julien merged 1 commits from feat/portal-shell/favicons-pwa-manifest into main 2026-05-11 01:03:05 +02:00
Owner

Summary

  • Replace the single root favicon.ico with a complete asset bundle under apps/portal-shell/public/favicons/: SVG primary favicon, PNG fallback (96×96), legacy ICO, Apple touch icon (180×180), and a Web App Manifest with 192 / 512 maskable PNGs.
  • Wire the assets in index.html via the standard <link rel="icon|apple-touch-icon|manifest"> block and add a matching <meta name="theme-color" content="#ffffff">.
  • Set the manifest name to "APF Portal" (short_name "Portal") so the PWA install banner and home-screen icon read consistently with the in-app header.

Why it matters

  • Modern favicons. SVG is now the primary icon — vector-clean at every density, automatic dark-mode adaptation when the SVG carries prefers-color-scheme rules. PNG + ICO entries cover legacy and pinned-tab contexts.
  • Installability. With a valid manifest + 192/512 icons + display: standalone, the portal is installable on Android home-screens and as a desktop PWA in Chromium-based browsers, without shipping a service worker.
  • Mobile chrome. <meta name="theme-color"> aligned with the manifest's theme_color tints the browser address bar and the PWA chrome to white — matching the app header.

Decisions worth flagging

  • Icons declared purpose: "maskable" only. The PNGs were generated with the Android safe-zone padding. On Android they render correctly (cropped to the device's adaptive shape); on contexts that ask for "any" the browser falls back to the SVG / PNG / ICO entries from the <link rel="icon"> block, so nothing breaks. If we later want a no-padding edge-to-edge variant for desktop, we can add a second icon entry with purpose: "any" and a different source.
  • theme_color: #ffffff rather than brand teal. The app header is white in the v1 design; tinting the mobile chrome to teal would create a visible seam at the top of the viewport. We can revisit if a darker header lands.
  • Cache-buster query strings kept (?v=20260511). Static public/ assets are not hashed by Angular's build (only bundled JS/CSS are), so the explicit version stamp guards against stale caches on icon updates. The date matches the generation day.

What this PR explicitly does NOT do

  • Ship a service worker / offline support (PWA installability does not require it; offline strategy is a separate decision and likely a future ADR).
  • Replace the SVG icon contents with a brand-tuned design — uses the existing generator output.
  • Wire a localized manifest (single name / short_name, no lang variant per locale).

Test plan

  • pnpm exec nx build portal-shell --configuration=production — green, 100 kB gzip initial (unchanged).
  • All 7 assets ship to dist/apps/portal-shell/browser/favicons/.
  • index.html in the production build contains every <link> + the theme-color meta.
  • Manual: tab favicon visible in Chrome / Firefox / Safari.
  • Manual: Chrome DevTools → Application → Manifest reports no errors and shows both 192/512 icons.
  • Manual: Chrome desktop install prompt offers "Install APF Portal".
  • Manual: Add-to-Home-Screen on Android shows the maskable icon clipped to the device's adaptive shape.
## Summary - Replace the single root `favicon.ico` with a complete asset bundle under [`apps/portal-shell/public/favicons/`](apps/portal-shell/public/favicons/): SVG primary favicon, PNG fallback (96×96), legacy ICO, Apple touch icon (180×180), and a Web App Manifest with 192 / 512 maskable PNGs. - Wire the assets in [`index.html`](apps/portal-shell/src/index.html) via the standard `<link rel="icon|apple-touch-icon|manifest">` block and add a matching `<meta name="theme-color" content="#ffffff">`. - Set the manifest name to `"APF Portal"` (short_name `"Portal"`) so the PWA install banner and home-screen icon read consistently with the in-app header. ## Why it matters - **Modern favicons.** SVG is now the primary icon — vector-clean at every density, automatic dark-mode adaptation when the SVG carries `prefers-color-scheme` rules. PNG + ICO entries cover legacy and pinned-tab contexts. - **Installability.** With a valid manifest + 192/512 icons + `display: standalone`, the portal is installable on Android home-screens and as a desktop PWA in Chromium-based browsers, without shipping a service worker. - **Mobile chrome.** `<meta name="theme-color">` aligned with the manifest's `theme_color` tints the browser address bar and the PWA chrome to white — matching the app header. ## Decisions worth flagging - **Icons declared `purpose: "maskable"` only.** The PNGs were generated with the Android safe-zone padding. On Android they render correctly (cropped to the device's adaptive shape); on contexts that ask for `"any"` the browser falls back to the SVG / PNG / ICO entries from the `<link rel="icon">` block, so nothing breaks. If we later want a no-padding edge-to-edge variant for desktop, we can add a second icon entry with `purpose: "any"` and a different source. - **`theme_color: #ffffff` rather than brand teal.** The app header is white in the v1 design; tinting the mobile chrome to teal would create a visible seam at the top of the viewport. We can revisit if a darker header lands. - **Cache-buster query strings kept (`?v=20260511`).** Static `public/` assets are not hashed by Angular's build (only bundled JS/CSS are), so the explicit version stamp guards against stale caches on icon updates. The date matches the generation day. ## What this PR explicitly does NOT do - Ship a service worker / offline support (PWA installability does not require it; offline strategy is a separate decision and likely a future ADR). - Replace the SVG icon contents with a brand-tuned design — uses the existing generator output. - Wire a localized manifest (single `name` / `short_name`, no `lang` variant per locale). ## Test plan - [x] `pnpm exec nx build portal-shell --configuration=production` — green, 100 kB gzip initial (unchanged). - [x] All 7 assets ship to `dist/apps/portal-shell/browser/favicons/`. - [x] `index.html` in the production build contains every `<link>` + the `theme-color` meta. - [ ] Manual: tab favicon visible in Chrome / Firefox / Safari. - [ ] Manual: Chrome DevTools → Application → Manifest reports no errors and shows both 192/512 icons. - [ ] Manual: Chrome desktop install prompt offers "Install APF Portal". - [ ] Manual: Add-to-Home-Screen on Android shows the maskable icon clipped to the device's adaptive shape.
julien added 1 commit 2026-05-11 01:02:07 +02:00
feat(portal-shell): full favicon set + PWA manifest
CI / scan (pull_request) Successful in 1m55s
CI / commits (pull_request) Successful in 2m5s
CI / check (pull_request) Successful in 2m29s
CI / a11y (pull_request) Successful in 1m36s
CI / perf (pull_request) Successful in 4m3s
810aa898d4
Drop in the realfavicongenerator-style asset bundle under
`public/favicons/`: SVG primary favicon, PNG fallback (96×96), legacy
ICO, Apple touch icon (180×180), and a Web App Manifest with 192/512
maskable PNGs for Android adaptive icons. Wire them in index.html via
the standard `<link rel="icon|apple-touch-icon|manifest">` block and
add a matching `<meta name="theme-color">` so the mobile chrome tints
align with the manifest.

PWA install banner reads "APF Portal" (short_name "Portal") on
home-screen and install prompts. theme + background colors stay white
to match the app header.

The old root-level `favicon.ico` is replaced by the one under
`public/favicons/` (referenced via `<link rel="shortcut icon">`).
julien merged commit 29f79d677e into main 2026-05-11 01:03:05 +02:00
julien deleted branch feat/portal-shell/favicons-pwa-manifest 2026-05-11 01:03:07 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#84