feat: re-enable blog post metadata and CodeBlock component

This commit is contained in:
Mauricio Siu
2025-03-02 21:22:14 -06:00
parent c9d02a98d4
commit 26cad40c68
3 changed files with 301 additions and 312 deletions

View File

@@ -14,7 +14,7 @@ import type { BundledLanguage } from "shiki/bundle/web";
import TurndownService from "turndown";
// @ts-ignore
import * as turndownPluginGfm from "turndown-plugin-gfm";
// import { CodeBlock } from "./components/CodeBlock";
import { CodeBlock } from "./components/CodeBlock";
import { H1, H2, H3 } from "./components/Headings";
import { TableOfContents } from "./components/TableOfContents";
import { ZoomableImage } from "./components/ZoomableImage";
@@ -22,50 +22,50 @@ type Props = {
params: { locale: string; slug: string };
};
// export async function generateMetadata(
// { params }: Props,
// parent: ResolvingMetadata,
// ): Promise<Metadata> {
// const { locale, slug } = await params;
// const post = await getPost(slug);
export async function generateMetadata(
{ params }: Props,
parent: ResolvingMetadata,
): Promise<Metadata> {
const { locale, slug } = await params;
const post = await getPost(slug);
// if (!post) {
// return {
// title: "Post Not Found",
// };
// }
if (!post) {
return {
title: "Post Not Found",
};
}
// const ogUrl = new URL(
// `/${locale}/api/og`,
// process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
// );
// ogUrl.searchParams.set("slug", slug);
const ogUrl = new URL(
`/${locale}/api/og`,
process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
);
ogUrl.searchParams.set("slug", slug);
// return {
// title: post.title,
// description: post.custom_excerpt || post.excerpt,
// openGraph: {
// title: post.title,
// description: post.custom_excerpt || post.excerpt,
// type: "article",
// url: `${process.env.NEXT_PUBLIC_APP_URL}/blog/${post.slug}`,
// images: [
// {
// url: ogUrl.toString(),
// width: 1200,
// height: 630,
// alt: post.title,
// },
// ],
// },
// twitter: {
// card: "summary_large_image",
// title: post.title,
// description: post.custom_excerpt || post.excerpt,
// images: [ogUrl.toString()],
// },
// };
// }
return {
title: post.title,
description: post.custom_excerpt || post.excerpt,
openGraph: {
title: post.title,
description: post.custom_excerpt || post.excerpt,
type: "article",
url: `${process.env.NEXT_PUBLIC_APP_URL}/blog/${post.slug}`,
images: [
{
url: ogUrl.toString(),
width: 1200,
height: 630,
alt: post.title,
},
],
},
twitter: {
card: "summary_large_image",
title: post.title,
description: post.custom_excerpt || post.excerpt,
images: [ogUrl.toString()],
},
};
}
export async function generateStaticParams() {
const posts = await getPosts();
@@ -80,10 +80,9 @@ export async function generateStaticParams() {
}
export default async function BlogPostPage({ params }: Props) {
try {
const { locale, slug } = await params;
const { slug } = await params;
// setRequestLocale(locale);
const t = await getTranslations({ locale, namespace: "blog" });
const t = await getTranslations("blog");
const post = await getPost(slug);
const allPosts = await getPosts();
@@ -106,14 +105,11 @@ export default async function BlogPostPage({ params }: Props) {
const markdown = turndownService.turndown(post.html);
const formattedDate = new Date(post.published_at).toLocaleDateString(
locale,
{
const formattedDate = new Date(post.published_at).toLocaleDateString("en", {
year: "numeric",
month: "long",
day: "numeric",
},
);
});
const components: Partial<Components> = {
h1: H1,
@@ -178,15 +174,15 @@ export default async function BlogPostPage({ params }: Props) {
className="object-cover max-w-lg mx-auto rounded-lg border max-lg:w-64 border-border overflow-hidden"
/>
),
// code: ({ className, children }) => {
// const match = /language-(\w+)/.exec(className || "");
// return (
// <CodeBlock
// lang={match ? (match[1] as BundledLanguage) : "ts"}
// code={children?.toString() || ""}
// />
// );
// },
code: ({ className, children }) => {
const match = /language-(\w+)/.exec(className || "");
return (
<CodeBlock
lang={match ? (match[1] as BundledLanguage) : "ts"}
code={children?.toString() || ""}
/>
);
},
};
return (
@@ -319,7 +315,7 @@ export default async function BlogPostPage({ params }: Props) {
{relatedPosts.map((relatedPost) => {
const relatedPostDate = new Date(
relatedPost.published_at,
).toLocaleDateString(locale, {
).toLocaleDateString("en", {
year: "numeric",
month: "long",
day: "numeric",
@@ -347,8 +343,7 @@ export default async function BlogPostPage({ params }: Props) {
{relatedPost.title}
</h3>
<p className="text-sm text-muted-foreground mb-4">
{relatedPostDate} {relatedPost.reading_time} min
read
{relatedPostDate} {relatedPost.reading_time} min read
</p>
<p className="text-muted-foreground line-clamp-2">
{relatedPost.excerpt}
@@ -363,8 +358,4 @@ export default async function BlogPostPage({ params }: Props) {
)}
</article>
);
} catch (error) {
console.error("Error in BlogPostPage:", error);
return <div>Error loading blog post</div>;
}
}

View File

@@ -2,11 +2,10 @@ import { getPosts, getTags } from "@/lib/ghost";
import type { Post } from "@/lib/ghost";
import { RssIcon } from "lucide-react";
import type { Metadata } from "next";
import { getTranslations, setRequestLocale } from "next-intl/server";
import { getTranslations } from "next-intl/server";
import Link from "next/link";
import { BlogPostCard } from "./components/BlogPostCard";
import { SearchAndFilter } from "./components/SearchAndFilter";
interface Tag {
id: string;
name: string;
@@ -27,8 +26,7 @@ export default async function BlogPage({
}) {
const { locale } = await params;
const searchParams2 = await searchParams;
setRequestLocale(locale);
const t = await getTranslations({ locale, namespace: "blog" });
const t = await getTranslations("blog");
const posts = await getPosts();
const tags = (await getTags()) as Tag[];
const search =

View File

@@ -11,8 +11,8 @@ type Props = {
};
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { tag, locale } = params;
const t = await getTranslations({ locale, namespace: "blog" });
const { tag } = await params;
const t = await getTranslations("blog");
return {
title: `${t("tagTitle", { tag })}`,
@@ -29,8 +29,8 @@ export async function generateStaticParams() {
}
export default async function TagPage({ params }: Props) {
const { locale, tag } = params;
const t = await getTranslations({ locale, namespace: "blog" });
const { tag } = await params;
const t = await getTranslations("blog");
const posts = await getPostsByTag(tag);
if (!posts || posts.length === 0) {