技術
約2分で読めます
【Astro】ドラフト機能を実装する
正月用の記事を事前に書いておきたい。でもコミットしたら公開されてしまう。
ブランチを分ける? .gitignore に追加? どれも面倒。
シンプルに draft: true で制御できるようにする。
要件
draft: trueの記事は本番ビルドで除外- 開発時は
[DRAFT]プレフィックス付きで表示(誤公開防止)
実装
1. スキーマに draft フィールドを追加
const articles = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
// ...他のフィールド
draft: z.boolean().optional(),
}),
});
2. 記事取得のヘルパー関数
import { getCollection, type CollectionEntry } from 'astro:content'
type ArticleFilter = (entry: CollectionEntry<'articles'>) => boolean
export async function getPublishedArticles(
filter?: ArticleFilter
): Promise<CollectionEntry<'articles'>[]> {
return getCollection('articles', (entry) => {
// 本番環境では draft 記事を除外
if (import.meta.env.PROD && entry.data.draft) {
return false
}
return filter ? filter(entry) : true
})
}
import.meta.env.PROD で本番/開発を判定。開発時(pnpm dev)はドラフトも表示される。
3. 各ページで使用
---
// Before
import { getCollection } from 'astro:content';
const articles = await getCollection('articles', ({ data }) => data.category === 'diary');
// After
import { getPublishedArticles } from '@/lib/articles';
const articles = await getPublishedArticles(({ data }) => data.category === 'diary');
---
既存のフィルタ条件はそのまま引数で渡せる。
4. 開発時の視認性向上
ArticleCard と記事詳細ページで、開発時のみタイトルに [DRAFT] を付ける。
---
const { title, draft } = Astro.props;
const displayTitle = !import.meta.env.PROD && draft ? `[DRAFT] ${title}` : title;
---
<h2>{displayTitle}</h2>
使い方
frontmatterに draft: true を追加。
---
title: "まだ公開しない記事"
draft: true
---
公開時は draft: true を削除するだけ。
まとめ
import.meta.env.PRODで本番/開発を判定- ヘルパー関数で一元管理
- 開発時のプレフィックス表示で誤公開を防止