ここでは、「Content Collections API」とMarkdownの tags
フロントマターを使って、タグごとの記事一覧ページを作成する手順を紹介します。
前提:
- Content Collections APIを使ってブログ記事 (
blog
コレクション) を管理していること。 - 各記事のMarkdownファイルのフロントマターに
tags
配列が設定されていること (例:tags: ["Astro", "初心者"]
)。
タグ別記事一覧ページの作成手順
1.動的ルートファイルの作成 (src/pages/tags/[tag].astro
)
まず、タグごとのページを生成するための動的ルートファイルを作成します。src/pages/tags/
ディレクトリ(なければ作成)に [tag].astro
という名前でファイルを作成します。[tag]
の部分がURLのタグ名になります。
your-project/
└── src/
├── content/
│ └── blog/
├── pages/
│ ├── blog/
│ ├── tags/ <-- このディレクトリを作成
│ │ └── [tag].astro <-- このファイルを作成
│ └── [...slug].astro (個別記事ページ)
└── layouts/
2.getStaticPaths
の実装 (タグと記事リストの生成)
作成した src/pages/tags/[tag].astro
ファイルを開き、getStaticPaths
関数を実装します。この関数は、存在するすべてのタグに対してページを生成するようにAstroに指示し、各ページに必要なデータを渡します。
---
// src/pages/tags/[tag].astro
import { getCollection } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro'; // 適切なレイアウトを指定
export async function getStaticPaths() {
const allPosts = await getCollection('blog');
// 1. 全記事からユニークなタグを集める
const uniqueTags = new Set<string>();
allPosts.forEach((post) => {
// post.data.tags が存在する場合のみ処理 (?. オプショナルチェイニング)
post.data.tags?.forEach((tag) => {
uniqueTags.add(tag); // Setが自動で重複を除外
});
});
// 2. 各タグに対応するページ情報を作成
return Array.from(uniqueTags).map((tag) => {
// 3. このタグが含まれる記事だけをフィルタリング
const filteredPosts = allPosts.filter((post) =>
post.data.tags?.includes(tag)
);
// 4. ページのパスと渡すデータを返す
return {
params: { tag: tag }, // URLの [tag] 部分になる値
props: {
tag: tag, // ページコンポーネントで使うタグ名
posts: filteredPosts, // このタグの記事リスト
},
};
});
}
// getStaticPathsから渡されたデータを受け取る
const { tag, posts } = Astro.props;
// 記事を日付順にソート (任意)
posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
// URLを決定するヘルパー関数 (個別記事ページへのリンク用、前の手順から流用)
function getPostUrl(post) {
if (post.data.url) {
return `/${post.data.url}/`;
}
return `/blog/${post.slug}/`;
}
---
-
getCollection('blog')
で全記事を取得します。 -
Set
を使って、すべての記事からユニークなタグを集めます。post.data.tags?.forEach
の?.
でtags
がない記事でもエラーにならないようにします。 - 集めたユニークなタグ (
uniqueTags
) それぞれについて、map
で処理します。 -
filter
を使って、そのタグが含まれる記事 (filteredPosts
) を抽出します。 -
params: { tag }
でページのURL (例:/tags/Astro/
) を定義し、props: { tag, posts }
でページコンポーネントにタグ名とそのタグの記事リストを渡します。
3.タグ別記事リストの表示
getStaticPaths
の下に、ページのHTMLテンプレート部分を記述します。Astro.props
から渡された tag
と posts
を使って一覧を表示します。
---
// --- 上記の getStaticPaths と props の受け取りコード ---
---
<BaseLayout title={`タグ: ${tag}`}>
<h1>タグ: 「{tag}」 の記事一覧</h1>
<ul>
{posts.map((post) => (
<li>
<a href={getPostUrl(post)}>{post.data.title}</a>
<span style="font-size: 0.8em; margin-left: 8px;">
({post.data.pubDate.toLocaleDateString()})
</span>
</li>
))}
</ul>
<p>
<a href="/tags/">すべてのタグ一覧へ</a>
</p>
</BaseLayout>
-
Astro.props
からtag
とposts
を受け取ります。 - 受け取った
posts
配列をmap
でループ処理し、各記事へのリンクとタイトルなどを表示します。記事へのリンクは、前の手順で定義したgetPostUrl
ヘルパー関数を使うと便利です。 - ページ全体を適切なレイアウトコンポーネント (
<BaseLayout>
など) で囲みます。
4.全タグ一覧ページの作成 (src/pages/tags/index.astro
)
すべてのタグをリスト表示するページもあると便利です。src/pages/tags/index.astro
を作成します。
---
// src/pages/tags/index.astro
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro'; // 適切なレイアウトを指定
const allPosts = await getCollection('blog');
const uniqueTags = new Set<string>();
allPosts.forEach((post) => {
post.data.tags?.forEach((tag) => {
uniqueTags.add(tag);
});
});
const sortedTags = Array.from(uniqueTags).sort(); // アルファベット順にソート (任意)
---
<BaseLayout title="すべてのタグ">
<h1>すべてのタグ一覧</h1>
<ul>
{sortedTags.map((tag) => (
<li>
<a href={`/tags/${tag}/`}>{tag}</a>
</li>
))}
</ul>
</BaseLayout>
- タグ別ページと同様に全記事からユニークなタグを集めます。
- 集めたタグを
map
でループし、各タグのタグ別一覧ページ (/tags/タグ名/
) へのリンクを生成します。
5.開発サーバーで確認
ターミナルで開発サーバーを起動します。
npm run dev
# または pnpm dev, yarn dev
ブラウザで以下のURLにアクセスして確認してみましょう。
-
全タグ一覧ページ:
http://localhost:4321/tags/
-
タグ別記事一覧ページ:
http://localhost:4321/tags/Astro/
(例:Astro
タグのページ)
全タグ一覧ページが表示され、各タグをクリックするとそのタグが付いた記事の一覧ページに移動できれば成功です!