Add complete Open Graph metadata layer across all 20 pages

- Add og:title, og:description, og:image, og:url, og:type, og:site_name to BaseLayout
- Add og:locale (en_GB) + og:locale:alternate (fr_FR, nb_NO) multilingual signals
- Add article:published_time, article:section, article:author on all 5 article pages
- Add Twitter/X summary_large_image card and canonical link on every page
- Generate 13 Jazz Noir branded 1200x630 PNG OG images (satori + resvg-js)
- Add scripts/generate-og-images.mjs + Special Elite font for future regeneration
- Add public/images/articles/ and public/assets/ which were previously untracked

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 01:38:51 +02:00
parent e38e2bb68e
commit 6b509fe052
57 changed files with 919 additions and 1 deletions
+36
View File
@@ -11,12 +11,20 @@ interface Props {
title?: string;
description?: string;
lang?: string;
ogImage?: string;
ogType?: "website" | "article";
ogArticlePublishedTime?: string;
ogArticleSection?: string;
}
const {
title = "Dave Gilligan | Blue Note Logic",
description = "A literary, jazzy, technically serious online magazine for writing, consulting, education, languages, family, and AI.",
lang = "en",
ogImage,
ogType,
ogArticlePublishedTime,
ogArticleSection,
} = Astro.props;
const now = new Date();
@@ -39,6 +47,10 @@ const issueDate = {
};
const pathname = Astro.url.pathname.replace(/\/+$/, "") || "/";
const siteUrl = "https://davegilligan.com";
const canonicalUrl = siteUrl + (pathname === "/" ? "" : pathname);
const ogImageAbsolute = siteUrl + (ogImage ?? "/images/og/home.png");
const resolvedOgType = ogType ?? "website";
const activeSlug = pathname === "/" ? "home" : pathname.split("/").filter(Boolean)[0];
const primarySlugs = ["business", "education", "writing", "jazz-music", "ai-lab", "norway"];
const primaryNav = launchSections.filter((section) => primarySlugs.includes(section.slug));
@@ -61,6 +73,30 @@ const chromeCopy = getChromeCopy({ activeSlug, issueDate, articleKey });
<meta name="description" content={description} />
<meta name="generator" content={Astro.generator} />
<meta name="theme-color" content="#f6f0e1" />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:site_name" content="Dave Gilligan" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:type" content={resolvedOgType} />
<meta property="og:image" content={ogImageAbsolute} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content={title} />
<meta property="og:locale" content="en_GB" />
<meta property="og:locale:alternate" content="fr_FR" />
<meta property="og:locale:alternate" content="nb_NO" />
{resolvedOgType === "article" && ogArticlePublishedTime && (
<meta property="article:published_time" content={ogArticlePublishedTime} />
)}
{resolvedOgType === "article" && ogArticleSection && (
<meta property="article:section" content={ogArticleSection} />
)}
<meta property="article:author" content="https://davegilligan.com" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImageAbsolute} />
<link rel="icon" href="/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />