diff --git a/starters/nextjs-starter-approuter-ts/app/articles/page.tsx b/starters/nextjs-starter-approuter-ts/app/articles/page.tsx index e5805320..3540856c 100644 --- a/starters/nextjs-starter-approuter-ts/app/articles/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/articles/page.tsx @@ -41,6 +41,6 @@ export default async function ArticlesListTemplate() { export function generateMetadata() { return { title: "Decoupled Next PCC Demo", - description: "Generated by create-pantheon-decoupled-kit.", + description: "Articles", }; } diff --git a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx index 939ebcc6..98c46324 100644 --- a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx @@ -21,9 +21,6 @@ export default async function ArticlePage({ params }: ArticlePageProps) { return notFound(); } - const recommendedArticles = - await PCCConvenienceFunctions.getRecommendedArticles(article.id); - return (
diff --git a/starters/nextjs-starter-approuter-ts/app/page.tsx b/starters/nextjs-starter-approuter-ts/app/page.tsx index 9e0b5229..aaa47d2c 100644 --- a/starters/nextjs-starter-approuter-ts/app/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/page.tsx @@ -60,6 +60,6 @@ export default async function Home() { export function generateMetadata() { return { title: "Decoupled Next PCC Demo", - description: "Generated by create-pantheon-decoupled-kit.", + description: "Homepage", }; } diff --git a/starters/nextjs-starter-approuter-ts/lib/utils.ts b/starters/nextjs-starter-approuter-ts/lib/utils.ts index 382a9661..dad3b900 100644 --- a/starters/nextjs-starter-approuter-ts/lib/utils.ts +++ b/starters/nextjs-starter-approuter-ts/lib/utils.ts @@ -1,5 +1,6 @@ import { ArticleWithoutContent } from "@pantheon-systems/pcc-react-sdk"; import { clsx, type ClassValue } from "clsx"; +import { Metadata } from "next"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { @@ -15,46 +16,46 @@ export function formatDate(input: string | number): string { }); } -interface DateInputObject { - msSinceEpoch: string; -} - -function isDateInputObject(v: DateInputObject | unknown): v is DateInputObject { - return (v as DateInputObject).msSinceEpoch != null; -} - -export function getSeoMetadata(article: ArticleWithoutContent) { - const tags = article.tags && article.tags.length > 0 ? article.tags : []; - let authors = []; - let publishedTime = null; - - // Collecting data from metadata fields - Object.entries(article.metadata || {}).forEach(([key, val]) => { - if (key.toLowerCase().trim() === "author" && val) authors = [val]; - else if (key.toLowerCase().trim() === "date" && isDateInputObject(val)) - publishedTime = new Date(val.msSinceEpoch).toISOString(); - }); - +export function getSeoMetadata(article: ArticleWithoutContent): Metadata { + const tags: string[] = + article.tags && article.tags.length > 0 ? article.tags : []; const imageProperties = [ + article.metadata?.image, article.metadata?.["Hero Image"], // Extend as needed ] .filter((url): url is string => typeof url === "string") .map((url) => ({ url })); + const description = article.metadata?.description + ? String(article.metadata?.description) + : "Article hosted using Pantheon Content Cloud"; + + let authors: Metadata["authors"] = []; - const description = "Article hosted using Pantheon Content Publisher"; + // Collecting data from metadata fields + Object.entries(article.metadata || {}).forEach(([k, v]) => { + const key = k.toLowerCase().trim(); + + switch (key) { + case "author": { + if (typeof v === "string") { + authors = [{ name: v }]; + } + break; + } + } + }); return { title: article.title, description, - tags, + keywords: tags, authors, - publishedTime, openGraph: { type: "website", title: article.title, - description, images: imageProperties, + description, }, }; } diff --git a/starters/nextjs-starter-ts/lib/utils.ts b/starters/nextjs-starter-ts/lib/utils.ts index 66ed1afc..1379565f 100644 --- a/starters/nextjs-starter-ts/lib/utils.ts +++ b/starters/nextjs-starter-ts/lib/utils.ts @@ -1,5 +1,6 @@ import { ArticleWithoutContent } from "@pantheon-systems/pcc-react-sdk"; import { clsx, type ClassValue } from "clsx"; +import { OpenGraph } from "next-seo/lib/types"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { @@ -24,30 +25,58 @@ function isDateInputObject(v: DateInputObject | unknown): v is DateInputObject { } export function getSeoMetadata(article: ArticleWithoutContent) { - const tags = article.tags && article.tags.length > 0 ? article.tags : []; - let authors = []; - let publishedTime = null; - - // Collecting data from metadata fields - Object.entries(article.metadata || {}).forEach(([key, val]) => { - if (key.toLowerCase().trim() === "author" && val) authors = [val]; - else if (key.toLowerCase().trim() === "date" && isDateInputObject(val)) - publishedTime = new Date(val.msSinceEpoch).toISOString(); - }); - + const tags: string[] = + article.tags && article.tags.length > 0 ? article.tags : []; const imageProperties = [ + article.metadata?.image, article.metadata?.["Hero Image"], // Extend as needed ] .filter((url): url is string => typeof url === "string") .map((url) => ({ url })); + const description = article.metadata?.description + ? String(article.metadata?.description) + : "Article hosted using Pantheon Content Cloud"; + + let authors: string[] = []; + let publishedTime: number | null = article.publishedDate; + + // Collecting data from metadata fields + Object.entries(article.metadata || {}).forEach(([k, v]) => { + const key = k.toLowerCase().trim(); + + switch (key) { + case "author": { + if (typeof v === "string") { + authors = [v]; + } + break; + } + case "date": { + if (isDateInputObject(v)) { + // Prefer the date from the metadata, if it exists + publishedTime = parseInt(v.msSinceEpoch); + } + break; + } + } + }); return { title: article.title, - description: "Article hosted using Pantheon Content Cloud", - tags, - authors, - publishedTime, - images: imageProperties, + description, + openGraph: { + type: "website", + title: article.title, + images: imageProperties, + description, + article: { + authors: authors, + tags: tags, + ...(publishedTime && { + publishedTime: new Date(publishedTime).toISOString(), + }), + }, + } satisfies OpenGraph, }; } diff --git a/starters/nextjs-starter-ts/pages/articles/[...uri].tsx b/starters/nextjs-starter-ts/pages/articles/[...uri].tsx index ea038d46..45a6531a 100644 --- a/starters/nextjs-starter-ts/pages/articles/[...uri].tsx +++ b/starters/nextjs-starter-ts/pages/articles/[...uri].tsx @@ -29,19 +29,7 @@ export default function ArticlePage({ article, grant }: ArticlePageProps) {
diff --git a/starters/nextjs-starter-ts/pages/examples/ssg-isr/[uri].tsx b/starters/nextjs-starter-ts/pages/examples/ssg-isr/[uri].tsx index d1e681c6..bccc4e94 100644 --- a/starters/nextjs-starter-ts/pages/examples/ssg-isr/[uri].tsx +++ b/starters/nextjs-starter-ts/pages/examples/ssg-isr/[uri].tsx @@ -5,19 +5,14 @@ import { import { GetStaticPaths, GetStaticProps } from "next"; import { NextSeo } from "next-seo"; import { StaticArticleView } from "../../../components/article-view"; -import { ArticleGrid } from "../../../components/grid"; import Layout from "../../../components/layout"; import { getSeoMetadata } from "../../../lib/utils"; interface ArticlePageProps { article: Article; - recommendedArticles: Article[]; } -export default function ArticlePage({ - article, - recommendedArticles, -}: ArticlePageProps) { +export default function ArticlePage({ article }: ArticlePageProps) { const seoMetadata = getSeoMetadata(article); return ( @@ -25,18 +20,7 @@ export default function ArticlePage({
@@ -64,13 +48,9 @@ export const getStaticProps: GetStaticProps<{}, { uri: string }> = async ({ }; } - const recommendedArticles = - await PCCConvenienceFunctions.getRecommendedArticles(article.id); - return { props: { article, - recommendedArticles, }, }; } catch (e) { diff --git a/starters/nextjs-starter/lib/utils.js b/starters/nextjs-starter/lib/utils.js index ad627ff5..0d244d47 100644 --- a/starters/nextjs-starter/lib/utils.js +++ b/starters/nextjs-starter/lib/utils.js @@ -20,29 +20,56 @@ function isDateInputObject(v) { export function getSeoMetadata(article) { const tags = article.tags && article.tags.length > 0 ? article.tags : []; - let authors = []; - let publishedTime = null; - - // Collecting data from metadata fields - Object.entries(article.metadata || {}).forEach(([key, val]) => { - if (key.toLowerCase().trim() === "author" && val) authors = [val]; - else if (key.toLowerCase().trim() === "date" && isDateInputObject(val)) - publishedTime = new Date(val.msSinceEpoch).toISOString(); - }); - const imageProperties = [ + article.metadata?.image, article.metadata?.["Hero Image"], // Extend as needed ] .filter((url) => typeof url === "string") .map((url) => ({ url })); + const description = article.metadata?.description + ? String(article.metadata?.description) + : "Article hosted using Pantheon Content Cloud"; + + let authors = []; + let publishedTime = article.publishedDate; + + // Collecting data from metadata fields + Object.entries(article.metadata || {}).forEach(([k, v]) => { + const key = k.toLowerCase().trim(); + + switch (key) { + case "author": { + if (typeof v === "string") { + authors = [v]; + } + break; + } + case "date": { + if (isDateInputObject(v)) { + // Prefer the date from the metadata, if it exists + publishedTime = parseInt(v.msSinceEpoch); + } + break; + } + } + }); return { title: article.title, - description: "Article hosted using Pantheon Content Cloud", - tags, - authors, - publishedTime, - images: imageProperties, + description, + openGraph: { + type: "website", + title: article.title, + images: imageProperties, + description, + article: { + authors: authors, + tags: tags, + ...(publishedTime && { + publishedTime: new Date(publishedTime).toISOString(), + }), + }, + }, }; } diff --git a/starters/nextjs-starter/pages/articles/[...uri].jsx b/starters/nextjs-starter/pages/articles/[...uri].jsx index 12cb57bf..ee9c327c 100644 --- a/starters/nextjs-starter/pages/articles/[...uri].jsx +++ b/starters/nextjs-starter/pages/articles/[...uri].jsx @@ -23,19 +23,7 @@ export default function ArticlePage({ article, grant }) {
diff --git a/starters/nextjs-starter/pages/examples/ssg-isr/[uri].jsx b/starters/nextjs-starter/pages/examples/ssg-isr/[uri].jsx index 7ed1dac5..ca09d9b2 100644 --- a/starters/nextjs-starter/pages/examples/ssg-isr/[uri].jsx +++ b/starters/nextjs-starter/pages/examples/ssg-isr/[uri].jsx @@ -1,7 +1,6 @@ import { PCCConvenienceFunctions } from "@pantheon-systems/pcc-react-sdk"; import { NextSeo } from "next-seo"; import { StaticArticleView } from "../../../components/article-view"; -import { ArticleGrid } from "../../../components/grid"; import Layout from "../../../components/layout"; import { getSeoMetadata } from "../../../lib/utils"; @@ -13,18 +12,7 @@ export default function ArticlePage({ article, recommendedArticles }) {