前回からの続きです。
【Astro入門】トップページに新着記事一覧を表示!getCollectionを使ったデータ取得と並び替え
今回は、Astroのコンテンツコレクションをさらに活用して、「日記用のブログ」と「専門的な技術記事」のディレクトリを分けて管理する方法を説明します。
例えば、日々の日記は「blog」ディレクトリへ、ゲームの情報や攻略などの内容は「game」ディレクトリへ分けることで、読者にとっても検索エンジン(SEO)にとっても分かりやすいサイト構造を作ることができます。
ディレクトリを分けて管理するメリット
ディレクトリ(コレクション)を分ける最大のメリットは、記事の種類ごとに「ルール(フロントマターの必須項目)」を変えられることです。
- 日記(blog): タイトルと日付だけで気軽に書けるルール。
- ゲーム記事(game): タイトル、日付に加えて「タグ(tags)」を必須にするルール
このように、用途に合わせて柔軟なデータ管理が可能になります。
作業内容
今回は、新しく「game」というカテゴリを追加するために、以下の作業を行っていきます。
- src/content/gameディレクトリの作成
- 新しいコレクション(ゲーム記事)のMarkdownファイルを保存するための専用フォルダを作ります。
- src/content/config.tsにルール追加
- 作成した「game」ディレクトリ内の記事に対して、「タグ(tags)を必須にする」といった独自のルール(スキーマ)を追加設定します。
- src/pages/gameディレクトリの作成
- ブラウザでアクセスしたときのURL(例:http://localhost:4321/game/)の土台となるディレクトリを作ります。
- src/pages/game/[slug].astroの作成
- 「game」ディレクトリに保存された記事データを読み込み、実際にHTMLとして画面に表示するための「個別記事用のテンプレート」を作成します。
前回までの「blog」ディレクトリ作成の作業と近いですね。
新しいディレクトリを作成する
まずは、これまでマークダウン形式の記事を作成していた「src/content/blog」とは別に、新しい「src/content/game」ディレクトリを作成します。
src/content/
├── blog/ ← 今までの日記用
│ └── 2026/03/13/index.md
└── game/ ← 新しく作るゲーム記事用ディレクトリ
└── tails-series/
└── index.md
「src/content/config.ts」に新しいルールを追記する
Astroでは、プロジェクト全体で「src/content/config.ts」は1つだけと決まっていて、すべてのコレクションのルールをまとめる役割を果たしています。
そのため、新しいディレクトリを作ったからといって、新しい「config.ts」を作成してはいけません。
ですので、既存の「src/content/config.ts」に、以下のように「game」用のルールを書き足します。
import { defineCollection, z } from 'astro:content';
// 今までの blog 用のルール(そのまま残します)
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pubDate: z.date(),
description: z.string(),
author: z.string(),
}),
});
// game用のルールを追記
// (tagsを必須にしてみます)
const gameCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pubDate: z.date(),
description: z.string(),
author: z.string(),
tags: z.array(z.string()), // 記事にはタグを必須にする
}),
});
// 使用するコレクションにgameを追加
export const collections = {
'blog': blogCollection,
'game': gameCollection // ここに追加
};
コードの解説
前回も解説しているので簡単に説明します。
- const gameCollection = defineCollection({ ... })
-
「blogCollection」と同じように、新しく「gameCollection」という名前でルールの塊(スキーマ)を定義します。
- tags: z.array(z.string()),tagsを必ず追加するルールを追加し、複数のタグを取り込めるように配列(z.array)を使用
- export const collections = { ... }
-
ファイルの一番下にあるこの部分が、Astro本体への「登録リスト」です。
すでに登録されている「'blog': blogCollection」の下に、カンマ(「,」)で区切って「'game': gameCollection」を追加します。
src/pages/gameディレクトリを作成する
Astroは「src/pages」ディレクトリの中身がそのままURLの構造になるというルールがあります。
そのため、「game」というURLを作るために、新しく「src/pages」ディレクトリの中に「game」というディレクトリを作ります。
src/pages/
├── index.astro ← トップページ
├── blog/
│ └── [slug].astro ← 今までの日記用ページ
└── game/ ← 新しく作るディレクトリ
└── [slug].astro ← 新しく作るファイル
[slug].astroファイルの作成
記事のデータを取得して表示するための「src/pages/game/[slug].astro」ファイルを新しく作成します。
基本的には「blog」の時とほぼ同じですが、記事の取得先が「game」に変わっているのと、tagsの中身を表示する設定が追加されます。
---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
// gameコレクションの記事だけを全て取得して、URLのパスを生成する
export async function getStaticPaths() {
const gameEntries = await getCollection('game'); // ここが 'game' になります!
return gameEntries.map(entry => {
// URLを短く綺麗にする処理(blogの時と同じです)
const cleanSlug = entry.slug.split('/').pop();
return {
params: { slug: cleanSlug },
props: { entry },
};
});
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<BaseLayout pageTitle={entry.data.title} pageDescription={entry.data.description}>
<article>
<h1>{entry.data.title}</h1>
<p>公開日: {entry.data.pubDate.toLocaleDateString('ja-JP')}</p>
<p>著者: {entry.data.author}</p>
<p>
Tags: {
entry.data.tags && entry.data.tags.map((tag) => (
<strong>
#{tag}
</strong>
))
}
</p>
<hr />
<Content />
</article>
</BaseLayout>
コードの解説(blog用との違い)
- getCollection('game')
-
前回は「getCollection('blog')」でしたが、今回はゲーム記事を取得したいので「'game'」 を指定します。
これで Astro が自動的に「src/content/game」の中身を探しに行ってくれます。 - entry.data.tags && entry.data.tags.map((tag) => ( ... ))
-
記事(index.md)のフロントマターで設定したtagsの内容を、配列(例:["RPG", "テイルズ"])から、データを1つずつ「tag」という変数に取り出し、カッコの中のHTML(<strong>タグ)を繰り返し作成します。
最初に「entry.data.tags &&」と書くことで、「もしタグが設定されていなかったらエラーを出さずにスキップする」という安全対策(エラー回避)を行っています。
これは、config.tsでタグを必須にしてますが、後で任意に変更したい場合に備えての設定となります。 - #{tag}
- 取り出したタグの文字の前に「#」をつけて出力しています。これにより「#RPG」のように、よりタグらしい見た目になります。
設定反映
Podman環境を使用している場合、「compose.yaml」ファイルがあるディレクトリで以下のコマンドを実行し、コンテナを再起動して設定内容を反映させます。
$ cd ~/project/astro-dev $ podman-compose down $ podman-compose up -d
記事の作成と動作確認
「src/content/game/tails-series/index.md」といった記事を作成しました。
こちらの記事には「tags」を追加しています。
---
title: "テイルズシリーズについて"
pubDate: 2026-03-18
description: "テイルズシリーズについていろいろ書きます"
author: "tamohiko"
tags: ["RPG","テイルズシリーズ"]
slug: "tails-series"
---
# テイルズシリーズ
ここから下は、普通のMarkdownで本文を書いていきます。
# 発売されているタイトル
- テイルズオブファンタジア
動作確認
その後、ブラウザで「http://localhost:4321/game/tails-series」にアクセスします。
設定したtagsの内容やMarkdownの本文が綺麗に表示されていれば、コレクションの追加と分離は完璧に成功です。
これで、「blog」と「専門的なゲーム記事」を、それぞれ別のURLと別のルールで完全に切り分けて運用できるようになりました。



コメント