Skip to content

Commit c4e876b

Browse files
CopilotkingRayhan
andauthored
feat: use gray-matter frontmatter to extract page metadata
Agent-Logs-Url: https://github.com/techdiary-dev/techdiary.dev/sessions/bf323903-6c44-4c7a-b51d-fa811009688d Co-authored-by: kingRayhan <7611746+kingRayhan@users.noreply.github.com>
1 parent f0edfe2 commit c4e876b

4 files changed

Lines changed: 29 additions & 12 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"date-fns": "^4.1.0",
5252
"dotenv": "^16.4.7",
5353
"drizzle-orm": "^0.41.0",
54+
"gray-matter": "^4.0.3",
5455
"immer": "^10.1.1",
5556
"inngest": "^4.1.0",
5657
"jotai": "^2.12.2",

src/app/pages/[slug]/page.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,50 @@ import { existsSync, readFileSync } from "fs";
44
import { join } from "path";
55
import { Metadata } from "next";
66
import { notFound } from "next/navigation";
7+
import matter from "gray-matter";
78

89
interface Props {
910
params: Promise<{ slug: string }>;
1011
}
1112

12-
function slugToTitle(slug: string): string {
13-
return slug
14-
.split("-")
15-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
16-
.join(" ");
13+
interface PageData {
14+
content: string;
15+
title: string;
1716
}
1817

19-
async function getPageContent(slug: string): Promise<string | null> {
18+
async function getPageData(slug: string): Promise<PageData | null> {
2019
"use cache";
2120
const filePath = join(process.cwd(), "src/content", `${slug}.md`);
2221
if (!existsSync(filePath)) return null;
23-
return readFileSync(filePath, "utf-8");
22+
const raw = readFileSync(filePath, "utf-8");
23+
const { content, data } = matter(raw);
24+
const title =
25+
typeof data.title === "string" && data.title
26+
? data.title
27+
: slug
28+
.split("-")
29+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
30+
.join(" ");
31+
return { content, title };
2432
}
2533

2634
export async function generateMetadata({ params }: Props): Promise<Metadata> {
2735
const { slug } = await params;
28-
const title = slugToTitle(slug);
29-
return { title };
36+
const page = await getPageData(slug);
37+
return { title: page?.title ?? slug };
3038
}
3139

3240
const StaticMarkdownPage = async ({ params }: Props) => {
3341
const { slug } = await params;
34-
const content = await getPageContent(slug);
42+
const page = await getPageData(slug);
3543

36-
if (!content) notFound();
44+
if (!page) notFound();
3745

3846
return (
3947
<BaseLayout>
4048
<div className="max-w-3xl mx-auto my-10 px-4">
4149
<div className="content-typography">
42-
<Markdown content={content} />
50+
<Markdown content={page.content} />
4351
</div>
4452
</div>
4553
</BaseLayout>

src/content/privacy.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
---
2+
title: Privacy Policy
3+
---
4+
15
# Privacy Policy
26

37
*Last updated: April 2025*

src/content/terms-and-conditions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
---
2+
title: Terms and Conditions
3+
---
4+
15
# Terms and Conditions
26

37
*Last updated: April 2025*

0 commit comments

Comments
 (0)