330fecc3cc
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.
29 lines
1.5 KiB
TypeScript
29 lines
1.5 KiB
TypeScript
// src/app/manifest.ts
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Web App Manifest. Auto-served by Next.js at /manifest.webmanifest.
|
|
// Tells Android / Chrome / Edge "this site can be added to the home screen,
|
|
// here are the icons and how to launch it standalone".
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
import type { MetadataRoute } from "next";
|
|
import { getBranding } from "@/lib/siteSettings";
|
|
|
|
export default async function manifest(): Promise<MetadataRoute.Manifest> {
|
|
const branding = await getBranding();
|
|
|
|
return {
|
|
name: "FLUX | Energy, Directed.",
|
|
short_name: "FLUX",
|
|
description: "Advanced Radio Frequency Solutions by Patrizio Grando.",
|
|
start_url: "/",
|
|
display: "standalone",
|
|
background_color: "#F5F5F7",
|
|
theme_color: branding.themeColor,
|
|
icons: [
|
|
{ src: "/branding/favicon-192.png", sizes: "192x192", type: "image/png", purpose: "any" },
|
|
{ src: "/branding/favicon-512.png", sizes: "512x512", type: "image/png", purpose: "any" },
|
|
{ src: "/branding/favicon-512.png", sizes: "512x512", type: "image/png", purpose: "maskable" },
|
|
],
|
|
};
|
|
}
|