import { OG_HEIGHT, OG_WIDTH, SITE_OG_ALT, siteOgPath } from "~/lib/og";
type SeoInput = {
title: string;
/** Tab title when it differs from the shared title (e.g. private repositories share only a generic one). */
documentTitle?: string;
description?: string;
keywords?: string;
/** Forge origin (PUBLIC_URL); relative `path` and `image` are resolved against it. */
origin?: string;
/** Canonical page path, e.g. `/owner/repo`. */
path?: string;
/** Card path from ~/lib/og; defaults to the site card. */
image?: string;
imageAlt?: string;
};
function absolute(origin: string | undefined, path: string): string {
if (!origin) return path;
return new URL(path, origin).toString();
}
export const seo = ({ title, documentTitle, description, keywords, origin, path, image, imageAlt }: SeoInput) => {
const imageUrl = absolute(origin, image ?? siteOgPath());
const alt = imageAlt ?? (image ? title : SITE_OG_ALT);
const tags = [
{ title: documentTitle ?? title },
{ name: "description", content: description },
{ name: "keywords", content: keywords },
{ name: "twitter:card", content: "summary_large_image" },
{ name: "twitter:title", content: title },
{ name: "twitter:description", content: description },
{ name: "twitter:image", content: imageUrl },
{ name: "twitter:image:alt", content: alt },
{ property: "og:type", content: "website" },
{ property: "og:site_name", content: "gitfor" },
{ property: "og:title", content: title },
{ property: "og:description", content: description },
...(path ? [{ property: "og:url", content: absolute(origin, path) }] : []),
{ property: "og:image", content: imageUrl },