技術解説 2分で読めます

AstroのContent Collectionsで型安全なコンテンツ管理

Astroの Content Collections API を使って、型安全でスケーラブルなコンテンツ管理システムを構築する方法を解説します。

AstroのContent Collectionsで型安全なコンテンツ管理

AstroのContent Collections APIは、マークダウンやMDXファイルを型安全に管理できる強力な機能です。

Content Collectionsとは

Content Collectionsは、Astro 2.0で導入された機能で、以下のメリットがあります:

  • 型安全性: TypeScriptによる型チェック
  • スキーマ検証: Zodによるデータ検証
  • パフォーマンス: ビルド時の最適化
  • 開発体験: 自動補完とエラー検出

セットアップ

1. ディレクトリ構造

src/
└── content/
    ├── config.ts
    └── blog/
        └── first-post.mdx

2. スキーマ定義

src/content/config.tsでスキーマを定義します:

import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content',
  schema: ({ image }) => z.object({
    title: z.string(),
    date: z.date(),
    tags: z.array(z.string()),
    category: z.string(),
    coverImage: image().optional(),
    description: z.string(),
    draft: z.boolean().optional().default(false),
  }),
});

export const collections = {
  blog: blogCollection,
};

3. コンテンツの取得

import { getCollection } from 'astro:content';

// 全記事を取得
const allPosts = await getCollection('blog');

// 条件付き取得(下書きを除外)
const publishedPosts = await getCollection('blog',
  ({ data }) => !data.draft
);

// 特定の記事を取得
const post = await getEntry('blog', 'first-post');

実践例:ブログ一覧ページ

---
import { getCollection } from 'astro:content';

const posts = (await getCollection('blog', ({ data }) => !data.draft))
  .sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
---

<ul>
  {posts.map((post) => (
    <li>
      <a href={`/blog/${post.slug}`}>
        <h2>{post.data.title}</h2>
        <time>{post.data.date.toLocaleDateString()}</time>
      </a>
    </li>
  ))}
</ul>

まとめ

Content Collections APIを使うことで:

  1. 型安全性: コンパイル時にエラーを検出
  2. スケーラビリティ: 大量のコンテンツでも高速
  3. 保守性: スキーマで一元管理

ぜひ活用してみてください!

参考リンク