Use same-origin /api in the browser so builds are not stuck with baked-in localhost. Server-side fetches use INTERNAL_API_URL, NEXT_PUBLIC_API_URL, or loopback. Centralize logic in lib/api-base.ts. Made-with: Cursor
84 lines
2.2 KiB
TypeScript
84 lines
2.2 KiB
TypeScript
import type { Metadata } from "next";
|
|
import BlogPostClient from "./BlogPostClient";
|
|
import { BlogPostingJsonLd, BreadcrumbJsonLd } from "@/components/public/JsonLd";
|
|
import { apiUrl } from "@/lib/api-base";
|
|
|
|
async function fetchPost(slug: string) {
|
|
try {
|
|
const res = await fetch(apiUrl(`/posts/${slug}`), {
|
|
next: { revalidate: 300 },
|
|
});
|
|
if (!res.ok) return null;
|
|
return res.json();
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
interface Props {
|
|
params: Promise<{ slug: string }>;
|
|
}
|
|
|
|
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|
const { slug } = await params;
|
|
const post = await fetchPost(slug);
|
|
if (!post) {
|
|
return { title: "Post Not Found" };
|
|
}
|
|
|
|
const description =
|
|
post.excerpt ||
|
|
`Read "${post.title}" on the Belgian Bitcoin Embassy blog.`;
|
|
const author = post.authorName || "Belgian Bitcoin Embassy";
|
|
const ogImageUrl = `/og?title=${encodeURIComponent(post.title)}&type=blog`;
|
|
|
|
return {
|
|
title: post.title,
|
|
description,
|
|
openGraph: {
|
|
type: "article",
|
|
title: post.title,
|
|
description,
|
|
publishedTime: post.publishedAt || post.createdAt,
|
|
authors: [author],
|
|
images: [{ url: ogImageUrl, width: 1200, height: 630, alt: post.title }],
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: post.title,
|
|
description,
|
|
images: [ogImageUrl],
|
|
},
|
|
alternates: { canonical: `/blog/${slug}` },
|
|
};
|
|
}
|
|
|
|
export default async function BlogDetailPage({ params }: Props) {
|
|
const { slug } = await params;
|
|
const post = await fetchPost(slug);
|
|
|
|
return (
|
|
<>
|
|
{post && (
|
|
<>
|
|
<BlogPostingJsonLd
|
|
title={post.title}
|
|
description={post.excerpt || `Read "${post.title}" on the Belgian Bitcoin Embassy blog.`}
|
|
slug={slug}
|
|
publishedAt={post.publishedAt || post.createdAt}
|
|
authorName={post.authorName}
|
|
/>
|
|
<BreadcrumbJsonLd
|
|
items={[
|
|
{ name: "Home", href: "/" },
|
|
{ name: "Blog", href: "/blog" },
|
|
{ name: post.title, href: `/blog/${slug}` },
|
|
]}
|
|
/>
|
|
</>
|
|
)}
|
|
<BlogPostClient slug={slug} />
|
|
</>
|
|
);
|
|
}
|