Commit Graph

1 Commits

Author SHA1 Message Date
davidherran 330fecc3cc feat: favicon multi-variant — 1 upload generates 6 sizes + PWA manifest
Deploy to VPS / deploy (push) Has been cancelled
The single-favicon upload was leaving most platforms with the wrong icon:
Android Chrome looks for 192×192, iOS for 180×180, Windows for 48×48,
HiDPI tabs for 32×32, legacy tabs for 16×16, PWA splash for 512×512 —
six different files, all from the same source image.

ONE EDITOR ACTION → SIX FILES
- POST /api/branding/favicon takes a single PNG/JPG/WebP (≥ 192×192,
  ideally 512×512+) and runs it through sharp to produce:
    /branding/favicon-16.png    /branding/favicon-32.png
    /branding/favicon-48.png    /branding/favicon-180.png
    /branding/favicon-192.png   /branding/favicon-512.png
    /branding/favicon-master.png  (kept for re-generation)
- Square-ish source images get center-cropped automatically.
- Returns the variant list + soft warnings ("not square — center-cropped",
  "upload at least 512×512 for retina") so the editor sees what happened.
- Validates dimensions and file type, caps at 20MB.

ROOT LAYOUT (src/app/[locale]/layout.tsx)
- Detects whether the multi-variant set exists on disk. If yes, emits
  <link rel="icon" sizes="16x16 / 32x32 / 192x192">, an explicit
  Apple touch link, and a Safari pinned-tab mask-icon. If no, falls
  back to the legacy single faviconUrl from SiteSetting.
- Adds <link rel="manifest" href="/manifest.webmanifest"> so Android
  Chrome surfaces "Add to Home Screen" properly.

PWA MANIFEST (src/app/manifest.ts)
- Auto-served at /manifest.webmanifest via Next.js's MetadataRoute.
- Pulls themeColor from SiteSetting.branding so editor changes there
  cascade to the standalone-app theme.
- Lists 192 + 512 icons with both 'any' and 'maskable' purposes for
  Android adaptive icons.

HQ SETTINGS UX (src/app/hq-command/dashboard/settings/page.tsx)
- New <FaviconMasterField/> at the top of the Branding tab — replaces
  the old standalone Favicon ImageField. Shows a 32×32 preview, an
  upload button, the generation result with each variant's preview,
  and warnings when the source isn't ideal.
- The Apple Touch Icon ImageField below it stays as an override path
  for editors who want a different icon on iOS (rare, but supported).
- Cache buster query string on previews so re-uploads visibly refresh
  without forcing the editor to hard-reload.

NO BACKEND/DB CHANGES OUTSIDE FILE I/O.
The SiteSetting.branding row is unchanged. The favicon variants are
plain files on disk under public/branding/, served by Nginx with the
existing 5-min cache headers.
2026-05-05 19:07:16 -05:00