Skip to content

Commit c0b067f

Browse files
fix: convert blog data into right shape for Nextra components
1 parent 4e742e1 commit c0b067f

File tree

3 files changed

+74
-9
lines changed

3 files changed

+74
-9
lines changed

app/blog/get-posts.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
import { normalizePages } from 'nextra/normalize-pages'
22
import { getPageMap } from 'nextra/page-map'
3+
import type { RawBlogPost, BlogPost } from '../../types/blog'
34

4-
export async function getPosts() {
5+
export async function getPosts(): Promise<BlogPost[]> {
56
const { directories } = normalizePages({
67
list: await getPageMap('/blog'),
78
route: '/blog'
89
})
910

1011
return directories
1112
.filter(post => post.name !== 'page')
13+
.map(post => ({
14+
...post,
15+
frontMatter: post.frontMatter || {}
16+
}))
1217
.sort((a, b) => {
1318
const dateA = a.frontMatter?.date ? new Date(a.frontMatter.date).getTime() : 0
1419
const dateB = b.frontMatter?.date ? new Date(b.frontMatter.date).getTime() : 0
1520
return dateB - dateA
1621
})
1722
}
1823

19-
export async function getTags() {
24+
export async function getTags(): Promise<string[]> {
2025
const posts = await getPosts()
2126
const tags = posts.flatMap(post => post.frontMatter?.tags || [])
2227
return tags

app/blog/page.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import Link from 'next/link'
22
import { PostCard } from 'nextra-theme-blog'
33
import { getPosts, getTags } from './get-posts'
4+
import type { BlogMetadata, TagCount, PostCardData } from '../../types/blog'
45

5-
export const metadata = {
6+
export const metadata: BlogMetadata = {
67
title: 'Blog'
78
}
89

910
export default async function BlogIndexPage() {
1011
const tags = await getTags()
1112
const posts = await getPosts()
12-
const allTags = Object.create(null)
13+
const allTags: TagCount = {}
1314

1415
for (const tag of tags) {
15-
allTags[tag] ??= 0
16-
allTags[tag] += 1
16+
allTags[tag] = (allTags[tag] ?? 0) + 1
1717
}
1818

1919
return (
@@ -35,9 +35,24 @@ export default async function BlogIndexPage() {
3535
))}
3636
</div>
3737
)}
38-
{posts.map(post => (
39-
<PostCard key={post.route} post={post} />
40-
))}
38+
{posts.map(post => {
39+
// Transform blog post data to match PostCard component expectations
40+
// PostCard from nextra-theme-blog expects frontMatter to be BlogMetadata
41+
// (only title and description), not our extended frontMatter with date, tags, etc.
42+
const postCardData: PostCardData = {
43+
...post,
44+
frontMatter: {
45+
title: post.frontMatter.title || post.name,
46+
description: post.frontMatter.description
47+
}
48+
}
49+
return (
50+
<PostCard
51+
key={post.route}
52+
post={postCardData}
53+
/>
54+
)
55+
})}
4156
</div>
4257
)
4358
}

types/blog.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Raw post data from nextra
2+
export interface RawBlogPost {
3+
name: string
4+
route: string
5+
frontMatter?: {
6+
title?: string
7+
date?: string
8+
tags?: string[]
9+
description?: string
10+
[key: string]: any
11+
}
12+
[key: string]: any
13+
}
14+
15+
// Processed blog post for internal use
16+
export interface BlogPost {
17+
name: string
18+
route: string
19+
frontMatter: {
20+
title?: string
21+
date?: string
22+
tags?: string[]
23+
description?: string
24+
[key: string]: any
25+
}
26+
[key: string]: any
27+
}
28+
29+
// Type that PostCard component expects (matches BlogMetadata)
30+
// Note: PostCard from nextra-theme-blog only needs title and description
31+
// in frontMatter, not our extended frontMatter with date, tags, etc.
32+
export interface PostCardData {
33+
route: string
34+
frontMatter: BlogMetadata
35+
[key: string]: any
36+
}
37+
38+
export interface TagCount {
39+
[tag: string]: number
40+
}
41+
42+
export interface BlogMetadata {
43+
title: string
44+
description?: string
45+
}

0 commit comments

Comments
 (0)