chrome: brandIcons() — derive Next.js favicon metadata from Brand
Every app that imports the kit was shipping a /favicon.ico 404
because none of them wired up Next.js's metadata.icons. This adds
a tiny helper so an app only has to:
export const metadata: Metadata = {
title: brand.product,
icons: brandIcons(brand),
};
brandIcons() returns icon/shortcut/apple entries pointing at
brand.faviconUrl (new optional field, defaults to brand.logoUrl).
MIME type inferred from the URL extension (svg/png/ico).
Brand gains the optional faviconUrl field. Existing apps that just
pass logoUrl keep working — they'll now render the logo as the
favicon by default. Apps that want a separate icon set
faviconUrl explicitly.
First consumer: gscSounds layout — verified /favicon.ico now
serves the proper icon and /icon.svg works too.
This commit is contained in:
37
src/chrome/brandIcons.ts
Normal file
37
src/chrome/brandIcons.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Returns a Next.js Metadata `icons` object derived from a Brand.
|
||||||
|
// Apps drop this into their root layout's `metadata` export to ship
|
||||||
|
// the brand logo as the favicon — fixes the "favicon 404" every
|
||||||
|
// consumer of the kit was shipping with.
|
||||||
|
//
|
||||||
|
// import type { Metadata } from "next";
|
||||||
|
// import { brandIcons } from "@gsc/web-kit/chrome";
|
||||||
|
// import { brand } from "@/config/brand";
|
||||||
|
//
|
||||||
|
// export const metadata: Metadata = {
|
||||||
|
// title: brand.product,
|
||||||
|
// icons: brandIcons(brand),
|
||||||
|
// };
|
||||||
|
|
||||||
|
import type { Brand } from "./types";
|
||||||
|
|
||||||
|
interface BrandMetaIcons {
|
||||||
|
icon: { url: string; type?: string }[];
|
||||||
|
shortcut?: { url: string; type?: string }[];
|
||||||
|
apple?: { url: string; type?: string }[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function brandIcons(brand: Brand): BrandMetaIcons {
|
||||||
|
const url = brand.faviconUrl ?? brand.logoUrl;
|
||||||
|
// Heuristic: trust the file extension to set the MIME type. Most
|
||||||
|
// brand logos in the GoSec assets bucket are SVG.
|
||||||
|
const type =
|
||||||
|
/\.svg(\?|$)/i.test(url) ? "image/svg+xml" :
|
||||||
|
/\.png(\?|$)/i.test(url) ? "image/png" :
|
||||||
|
/\.ico(\?|$)/i.test(url) ? "image/x-icon" :
|
||||||
|
undefined;
|
||||||
|
return {
|
||||||
|
icon: [{ url, ...(type ? { type } : {}) }],
|
||||||
|
shortcut: [{ url }],
|
||||||
|
apple: [{ url }],
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ export {
|
|||||||
type CustomerOption,
|
type CustomerOption,
|
||||||
} from "./header";
|
} from "./header";
|
||||||
export { useChromeLabels, DEFAULT_CHROME_LABELS } from "./labels";
|
export { useChromeLabels, DEFAULT_CHROME_LABELS } from "./labels";
|
||||||
|
export { brandIcons } from "./brandIcons";
|
||||||
export type {
|
export type {
|
||||||
AdminShellProps,
|
AdminShellProps,
|
||||||
ActivityFeedItem,
|
ActivityFeedItem,
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export type Brand = {
|
|||||||
product: string; // "GoSec CRM"
|
product: string; // "GoSec CRM"
|
||||||
logoUrl: string; // full navbar logo
|
logoUrl: string; // full navbar logo
|
||||||
logoSmallUrl?: string; // optional compact logo
|
logoSmallUrl?: string; // optional compact logo
|
||||||
|
faviconUrl?: string; // optional favicon override (defaults to logoUrl)
|
||||||
websiteUrl: string; // footer brand link
|
websiteUrl: string; // footer brand link
|
||||||
supportUrl: string; // subbar Support + footer Support link
|
supportUrl: string; // subbar Support + footer Support link
|
||||||
docsUrl: string; // footer docs link
|
docsUrl: string; // footer docs link
|
||||||
|
|||||||
Reference in New Issue
Block a user