From 372e24eee66c267c9a4cc690418add2ae9e76be9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 07:59:12 +0000 Subject: [PATCH] fix: add Open Graph and Twitter Card metadata to all pages - closes #2691 - Add metadataBase, default openGraph, and twitter to app/layout.tsx so every route inherits OG image and Twitter Card metadata - Use SSW default OG image (1200x630) from Tina CDN - Import siteTitle, siteDescription, siteUrl, social from site-config to avoid duplication - Override openGraph title/description/url per-page in generateMetadata() for rules (type: article) and categories (type: website) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/[filename]/page.tsx | 28 ++++++++++++++++++++-------- app/layout.tsx | 29 ++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/app/[filename]/page.tsx b/app/[filename]/page.tsx index c114d2347..82b24a8ab 100644 --- a/app/[filename]/page.tsx +++ b/app/[filename]/page.tsx @@ -338,31 +338,43 @@ export async function generateMetadata({ params }: { params: Promise<{ filename: const category = await getCategoryData(filename); if (category?.data?.category && category.data.category.__typename === "CategoryCategory") { const categoryData = category.data.category as any; + const description = categoryData.seoDescription || undefined; + const canonicalUrl = `${siteUrl}/${filename}`; const metadata: any = { title: `${categoryData.title} | SSW.Rules`, + description, alternates: { - canonical: `${siteUrl}/${filename}`, + canonical: canonicalUrl, + }, + openGraph: { + title: `${categoryData.title} | SSW.Rules`, + description, + url: canonicalUrl, + type: "website", }, }; - if (categoryData.seoDescription) { - metadata.description = categoryData.seoDescription; - } - return metadata; } const rule = await getRuleData(filename); if (rule?.data?.rule?.title) { + const description = rule.data.rule.seoDescription || extractBodyPreview(rule.data.rule.body) || undefined; + const canonicalUrl = `${siteUrl}/${filename}`; const metadata: any = { title: `${rule.data.rule.title} | SSW.Rules`, + description, alternates: { - canonical: `${siteUrl}/${filename}`, + canonical: canonicalUrl, + }, + openGraph: { + title: `${rule.data.rule.title} | SSW.Rules`, + description, + url: canonicalUrl, + type: "article", }, }; - metadata.description = rule.data.rule.seoDescription || extractBodyPreview(rule.data.rule.body) || undefined; - if (rule.data.rule.isArchived) { metadata.robots = { index: false, follow: true }; } diff --git a/app/layout.tsx b/app/layout.tsx index caa097c9a..783449fe0 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -8,6 +8,7 @@ import "@/styles.css"; import UserClientProvider from "@/components/auth/UserClientProvider"; import AppInsightsProvider from "@/components/providers/AppInsightsProvider"; import { TailwindIndicator } from "@/components/ui/breakpoint-indicator"; +import { siteDescription, siteTitle, siteUrl, social } from "@/site-config"; const fontSans = FontSans({ subsets: ["latin"], @@ -25,10 +26,32 @@ const lato = Lato({ weight: "400", }); +const DEFAULT_OG_IMAGE = "https://assets.tina.io/8a7b77f2-cde8-44e7-a592-ebeb7e9dc437/ssw-default-og.jpg"; + export const metadata: Metadata = { - title: "SSW.Rules | Secret Ingredients to Quality Software (Open Source on GitHub)", - description: - "Secret Ingredients to Quality Software | SSW Rules provides best practices for developing secure, reliable, and efficient .NET, Azure, CRM, Angular, React, Dynamics, and AI applications. Learn more today!", + metadataBase: new URL("https://www.ssw.com.au"), + title: `${siteTitle} | Secret Ingredients to Quality Software (Open Source on GitHub)`, + description: siteDescription, + openGraph: { + title: `${siteTitle} | Secret Ingredients to Quality Software (Open Source on GitHub)`, + description: siteDescription, + siteName: siteTitle, + type: "website", + url: siteUrl, + images: [ + { + url: DEFAULT_OG_IMAGE, + width: 1200, + height: 630, + alt: `${siteTitle} - Secret Ingredients to Quality Software`, + }, + ], + }, + twitter: { + card: "summary_large_image", + site: `@${social.twitter}`, + creator: `@${social.twitter}`, + }, }; const jsonLd = [