【Astro】コンテンツコレクションで記事を管理する

目次

執筆時の作業環境は以下のとおりです。

  • MacOS: Sonoma 14.2.1
  • Node.js: v21.6.1
  • npm: v10.2.4
  • Astro: v4.4.0

コンテンツコレクションとは

Astroには、コンテンツコレクションというコンテンツ管理に特化した組み込みの機能があります。

src/content/ディレクトリ内にコンテンツのカテゴリ名となるディレクトリを作成し、その中に.md.mdxファイルを作成すると 作成した記事軍を一つのコレクションという塊で扱えます。今回はブログの記事を管理するのでsrc/content/blog/というディレクトリを作成しました。

Astroではsrc/pagesディレクトリ内でも.mdファイルなどでページを作ることはできるのですが、コンテンツコレクションを使うことでフロントマッターの型を定義できるというメリットがあります。型を定義することで、コレクション内のエントリーのメタデータの形式を統一し、より安全に開発を進められます。

コレクションを定義する

コレクションの定義は、src/content/config.tsのファイルで行います。

// 1. `astro:content`からユーティリティをインポート
import { defineCollection } from 'astro:content'0

// 2. コレクションを定義
const blogCollection = defineCollection({
  /* ... */
})

// 3. コレクションを登録するために、単一の`collections`オブジェクトをエクスポート
//    このキーは、"src/content"のコレクションのディレクトリ名と一致する必要があります。
export const collections = {
  blog: blogCollection,
}

コレクションのフロントマッターの型を定義する

フロントマッターの定義には、内部でZodを使っているようです。定義したコレクションのschemaプロパティの中にオブジェクト形式で記述していきます。

通常のTypeScriptの型の書き方ではなく、zオブジェクトを呼び出してそのメソッドで型を定義します。

// 1. ユーティリティを`astro:content`からインポート
import { z, defineCollection } from 'astro:content'

// 2. 各コレクションに`type`と`schema`を定義
const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    layout: z.literal('@/layouts/BlogLayout.astro'),
    title: z.string(),
    description: z.string(),
    keywords: z.string(),
    tags: z.array(z.string()),
    image: z.string().optional(),
    publishedDate: z.date(),
  }),
})

// 3. コレクションを登録するために、単一の`collections`オブジェクトをエクスポート
export const collections = {
  blog: blogCollection,
}

コンテンツコレクションをAstroページ内で呼び出す

作成したコレクションのデータをページ内で呼び出すにはgetCollectionAPIを使います。

const blogPosts = await getCollection('blog')とすることで、変数blogPostsにコレクション内の記事のデータが配列の形式で格納されます。

---
// getCollection をインポート
import { getCollection } from 'astro:content'

// 引数にコレクション名を指定してデータを取得
const blogPosts = await getCollection('blog')
---

<!-- 取得したデータをmapで展開して使用 -->
<ul>
  {
    blogPosts.map((post) => (
      <li>
        <a href={`/my-blog-url/${post.slug}`}>{post.data.title}</a>
        <time datetime={post.data.publishedDate.toISOString()}>{post.data.publishedDate.toDateString()}</time>
      </li>
    ))
  }
</ul>

Astroコンポーネントでは、トップレベルでawaitを使用できます

おわり

Astroのコンテンツコレクションの設定とデータの使い方でした。お読みいただきありがとうございます。

以上