import type { Metadata } from 'next' type MediaLike = | { height?: null | number; mimeType?: null | string; url?: null | string; width?: null | number } | null | undefined /** * Builds Next.js `icons` metadata (favicon / apple-touch-icon) from the panel's * favicon upload, so the browser tab AND Google get a proper . * * Why the plugin must do this (not the project): favicon-in-Google has strict * rules — a real in , square, ≥48×48, at a stable URL. * Leaving it to each project meant inconsistent hand-rolled tags and no favicon * in search results. This generates the tags correctly, every time, from the * panel field. * * Favicon is GLOBAL (same across pages), so call this once in the ROOT layout's * generateMetadata — not per page: * * import { buildIconsMetadata } from '@intecion/ipal-kit' * export async function generateMetadata(): Promise { * const settings = await getSettings(locale) * return buildIconsMetadata(settings.favicon) * } * * Google notes: it caches favicons separately and slowly (days/weeks), and only * shows them for icons it deems valid. Warn on too-small icons at upload time * (see the media validation hook) so editors don't ship a <48px favicon Google * will reject. */ export function buildIconsMetadata(favicon: MediaLike): Metadata { const url = favicon?.url if (!url) {return {}} const isSvg = favicon?.mimeType === 'image/svg+xml' || url.endsWith('.svg') return { icons: { // Main favicon. SVG scales; PNG should be ≥48×48 (ideally 96 or 192). icon: isSvg ? [{ type: 'image/svg+xml', url }] : [{ sizes: 'any', url }], // Apple touch icon (home-screen bookmark on iOS). Reuses the same asset. apple: [{ url }], }, } }