SEO: favicon metadata, Organization JSON-LD, favicon validation; R2 media (preconnect, generateFileURL per-collection), filename normalization

This commit is contained in:
2026-08-28 00:08:35 +02:00
parent f1f808d079
commit b9430e7ab6
25 changed files with 490 additions and 11 deletions
+54
View File
@@ -0,0 +1,54 @@
/**
* Builds Next.js `icons` metadata (favicon / apple-touch-icon) from the panel's
* favicon upload, so the browser tab AND Google get a proper <link rel="icon">.
*
* Why the plugin must do this (not the project): favicon-in-Google has strict
* rules — a real <link rel="icon"> in <head>, 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<Metadata> {
* 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) {
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
}
]
}
};
}
//# sourceMappingURL=buildIconsMetadata.js.map