diff --git a/src/app/articles/[slug]/page.tsx b/src/app/articles/[slug]/page.tsx index c55fcce..81f613c 100644 --- a/src/app/articles/[slug]/page.tsx +++ b/src/app/articles/[slug]/page.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { cleanExcerpt } from "@/lib/articles/excerpt"; import { redirect } from "next/navigation"; import ArticleDetailPage from "./ArticleDetailClient"; import type { Article } from "@/lib/articles/types"; @@ -53,12 +54,12 @@ export async function generateMetadata({ params }: PageProps): Promise } return { title: article.title, - description: article.excerpt, + description: cleanExcerpt(article.excerpt), alternates: { canonical: `/articles/${article.slug}` }, openGraph: { type: "article", title: article.title, - description: article.excerpt, + description: cleanExcerpt(article.excerpt), url: `/articles/${article.slug}`, images: [{ url: article.image, width: 1200, height: 630, alt: article.alt }], authors: [article.author], @@ -68,7 +69,7 @@ export async function generateMetadata({ params }: PageProps): Promise twitter: { card: "summary_large_image", title: article.title, - description: article.excerpt, + description: cleanExcerpt(article.excerpt), images: [article.image], creator: "@AV Beat", }, @@ -93,7 +94,7 @@ export default async function ArticlePage({ params }: PageProps) { "@context": "https://schema.org", "@type": "Article", headline: article.title, - description: article.excerpt, + description: cleanExcerpt(article.excerpt), image: [absoluteImage(article.image)], author: { "@type": "Person", name: article.author }, publisher: { diff --git a/src/app/news/[slug]/page.tsx b/src/app/news/[slug]/page.tsx index 0c83f21..b7238ef 100644 --- a/src/app/news/[slug]/page.tsx +++ b/src/app/news/[slug]/page.tsx @@ -8,6 +8,7 @@ import { getRelatedForumThreads, type RelatedForumThread, } from "@/lib/articles/legacy-source"; import { linkifyAndExtractMentions } from "@/lib/company-mentions"; +import { cleanExcerpt } from "@/lib/articles/excerpt"; import CompanyMentionsHover from "@/components/CompanyMentionsHover"; import CompaniesInThisStory from "@/components/CompaniesInThisStory"; import NewsArticleDetailClient from "./NewsArticleDetailClient"; @@ -58,14 +59,19 @@ export async function generateMetadata({ params }: PageProps): Promise if (!article) { return { title: "Article Not Found", description: "The article you are looking for does not exist." }; } + // Strip HTML from excerpt before stuffing into / + // openGraph / twitter — those MUST be plain text. Raw excerpts sometimes + // contain

...

, which Next.js then HTML-escapes, surfacing as + // literal `<p>` in page source. + const cleanDesc = cleanExcerpt(article.excerpt); return { title: `${article.title} — AV Beat`, - description: article.excerpt, + description: cleanDesc, alternates: { canonical: `/news/${article.slug}` }, openGraph: { type: "article", title: article.title, - description: article.excerpt, + description: cleanDesc, url: `/news/${article.slug}`, images: [{ url: article.image, width: 1200, height: 630, alt: article.alt }], authors: [article.author], @@ -75,7 +81,7 @@ export async function generateMetadata({ params }: PageProps): Promise twitter: { card: "summary_large_image", title: article.title, - description: article.excerpt, + description: cleanDesc, images: [article.image], creator: "@AV Beat", }, @@ -106,7 +112,7 @@ export default async function NewsArticlePage({ params }: PageProps) { "@context": "https://schema.org", "@type": "NewsArticle", headline: article.title, - description: article.excerpt, + description: cleanExcerpt(article.excerpt), image: [absoluteImage(article.image)], author: { "@type": "Person", name: article.author }, publisher: {