feat: add metadata generation for post detail page and improve description formatting
This commit is contained in:
parent
118d994746
commit
be855563bb
2 changed files with 82 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import Link from "next/link";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { notFound } from "next/navigation";
|
||||
import type { Metadata } from "next";
|
||||
import Header from "@/components/header";
|
||||
import DetailRawPanel from "@/components/detail-raw-panel";
|
||||
|
||||
|
|
@ -20,6 +21,20 @@ type Me = {
|
|||
role: "admin" | "writer" | "reader";
|
||||
};
|
||||
|
||||
function getSourceLabel(type: SourceType) {
|
||||
return type === "twitter" ? "X" : type === "pixiv" ? "Pixiv" : "-";
|
||||
}
|
||||
|
||||
function createDetailDescription(post: PostDetailResponse) {
|
||||
const author = post.author?.trim() || "unknown";
|
||||
const source = getSourceLabel(post.type);
|
||||
const tags = (post.tags ?? []).filter((tag) => tag.trim().length > 0).slice(0, 5);
|
||||
const tagText = tags.length > 0 ? ` | Tags: ${tags.join(", ")}` : "";
|
||||
return `${author} | ${source} post${tagText}`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function getApiBaseUrl() {
|
||||
const configuredBaseUrl = process.env.API_BASE_URL;
|
||||
if (configuredBaseUrl) {
|
||||
|
|
@ -78,6 +93,71 @@ async function fetchViewerRole(apiBaseUrl: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
|
||||
const { id } = await params;
|
||||
const fallbackTitle = `Detail ${id} | Akiyama Mizuki`;
|
||||
|
||||
try {
|
||||
const apiBaseUrl = await getApiBaseUrl();
|
||||
const post = await fetchPostDetail(apiBaseUrl, id);
|
||||
const detailUrl = `${apiBaseUrl}/detail/${id}`;
|
||||
|
||||
if (!post) {
|
||||
return {
|
||||
title: fallbackTitle,
|
||||
description: "Post detail",
|
||||
alternates: {
|
||||
canonical: detailUrl,
|
||||
},
|
||||
robots: {
|
||||
index: false,
|
||||
follow: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const source = getSourceLabel(post.type);
|
||||
const author = post.author?.trim() || "unknown";
|
||||
const title = `${author} | ${source}`;
|
||||
const description = createDetailDescription(post);
|
||||
const ogImages = post.mediaUrl
|
||||
? [
|
||||
{
|
||||
url: post.mediaUrl,
|
||||
alt: `${author} ${source}`,
|
||||
},
|
||||
]
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
alternates: {
|
||||
canonical: detailUrl,
|
||||
},
|
||||
openGraph: {
|
||||
type: "article",
|
||||
title,
|
||||
description,
|
||||
url: detailUrl,
|
||||
siteName: "Akiyama Mizuki",
|
||||
images: ogImages,
|
||||
},
|
||||
twitter: {
|
||||
card: post.mediaUrl ? "summary_large_image" : "summary",
|
||||
title,
|
||||
description,
|
||||
images: post.mediaUrl ? [post.mediaUrl] : undefined,
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
title: fallbackTitle,
|
||||
description: "Post detail",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default async function DetailPage({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
const apiBaseUrl = await getApiBaseUrl();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue