add dynamic tag pages to display blog posts by tags

This commit is contained in:
fiatcode 2026-01-22 17:15:08 +07:00
parent 0511d90911
commit 05dfaed605
2 changed files with 78 additions and 14 deletions

View file

@ -1,24 +1,29 @@
---
import { getCollection } from "astro:content";
import { getCollection, render, type CollectionEntry, type RenderResult } from "astro:content";
import Layout from "../../layouts/Layout.astro";
import BlogPost from "../../components/BlogPost.astro";
import { render } from "astro:content";
import type { CollectionEntry } from "astro:content";
interface Props {
post: CollectionEntry<"blog">;
}
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.id },
props: { post },
}));
const paths = await Promise.all(
posts.map(async (post) => {
const id = post.id;
const content = await render(post);
return {
params: { id },
props: { post, content },
};
})
);
return paths;
}
const { post } = Astro.props;
const renderedPost = await render(post);
interface Props {
post: CollectionEntry<"blog">;
content: RenderResult;
}
const { post, content } = Astro.props;
---
<Layout
@ -31,6 +36,6 @@ const renderedPost = await render(post);
date={post.data.date}
tags={post.data.tags}
>
<renderedPost.Content />
<content.Content />
</BlogPost>
</Layout>

View file

@ -0,0 +1,59 @@
---
import { getCollection, type CollectionEntry } from "astro:content";
import BlogPostCard from "../../components/BlogPostCard.astro";
import Layout from "../../layouts/Layout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
const tags = new Set<string>();
posts.forEach((post) => {
if (post.data.tags) {
post.data.tags.forEach((tag: string) => tags.add(tag));
}
});
return Array.from(tags).map((name) => {
const filteredPosts = posts.filter(
(post) => post.data.tags && post.data.tags.includes(name),
);
return {
params: { name },
props: { filteredPosts },
};
});
}
interface Props {
filteredPosts: CollectionEntry<"blog">[];
}
const { name } = Astro.params;
const { filteredPosts } = Astro.props;
---
<Layout
title={`Posts tagged with "${name}" - Dhemas Nurjaya`}
description={`Browse blog posts tagged with "${name}" by Dhemas Nurjaya`}
>
<h1 class="text-4xl font-bold mb-8">Posts tagged with "{name}"</h1>
{
filteredPosts.length > 0 ? (
<ul class="space-y-4">
{filteredPosts.map((post) => (
<li>
<BlogPostCard
id={post.id}
title={post.data.title}
date={post.data.date}
description={post.data.description}
tags={post.data.tags}
/>
</li>
))}
</ul>
) : (
<p class="text-lg text-zinc-400">No posts found with the tag "{name}".</p>
)
}
</Layout>