From 5bee326cea6a3ecacf8e8323a8c6ebf1eea1a84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Thu, 28 Dec 2023 10:16:17 +0400 Subject: [PATCH] feat(seo): json-ld, siblings article, json-ld, time tag --- app/blog/[...slug]/page.tsx | 124 ++++++++++++++++++++++++++++++------ app/blog/page.tsx | 18 ++---- app/blog/sitemap.ts | 17 +++++ app/sitemap.xml | 6 ++ components/PostCard.tsx | 31 +++++---- lib/blog-api.tsx | 3 + next-sitemap.config.js | 5 ++ package.json | 1 + pnpm-lock.yaml | 26 +++++++- public/main-sitemap.xml | 6 ++ 10 files changed, 193 insertions(+), 44 deletions(-) create mode 100644 app/blog/sitemap.ts create mode 100644 app/sitemap.xml create mode 100644 next-sitemap.config.js create mode 100644 public/main-sitemap.xml diff --git a/app/blog/[...slug]/page.tsx b/app/blog/[...slug]/page.tsx index 9405c20..d96cacc 100644 --- a/app/blog/[...slug]/page.tsx +++ b/app/blog/[...slug]/page.tsx @@ -1,8 +1,19 @@ import { Metadata, ResolvingMetadata } from "next"; +import Link from "next/link"; import { notFound } from "next/navigation"; import * as React from "react"; import { Container } from "@/components/Container"; +import { + PostCard, + PostCardAuthor, + PostCardBody, + PostCardDate, + PostCardFooter, + PostCardImage, + PostCardTag, + PostCardTitle, +} from "@/components/PostCard"; import { getArticleBySlug, getArticles, getDocMdxSource } from "@/lib/blog-api"; type Props = { @@ -48,33 +59,108 @@ export async function generateMetadata({ params }: Props): Promise { }; } +async function Siblings({ slug }: { slug: string }) { + const articles = await getArticles(); + const sideArticles = articles + .filter((article) => article.slug !== slug) + .map((value) => ({ value, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({ value }) => value) + .slice(0, 2); + return ( +
+

Read also

+
+ {sideArticles.map((article) => { + return ( + + + + + {article.category && ( + {article.category} + )} + {article.title} + + {article.author} +
|
+ +
+
+
+ + ); + })} +
+
+ ); +} + +const dateFormatter = new Intl.DateTimeFormat("en-US", { + dateStyle: "long", +}); + export default async function Page({ params }: Props) { const article = await getArticleFromParams(params); if (!article) { notFound(); } const source = await getDocMdxSource(article); + const jsonLd = { + "@context": "https://schema.org", + "@type": "NewsArticle", + headline: article.title, + image: [article.image.src], + datePublished: article.date, + dateModified: article.updatedAt ?? article.date, + author: [ + { + "@type": "Person", + name: article.author, + }, + ], + }; return ( -
+ <> +
+ +
+ {article.category && ( +
+ {article.category} +
+ )} +

{article.title}

+
+ +
|
+
{article.author}
+
+
+ {source} +
+