個人開発のサービスのコラム(Astro 製)で、大きく書き直した記事に「更新日」を表示しようとしました。frontmatter に updatedDate を書いたのですが、エラーも警告も出ないのに、ページのどこにも反映されませんでした。
---
title: "海外旅行の割り勘どうする?"
pubDate: 2026-03-26
updatedDate: 2026-10-01
---
原因:スキーマにない項目は取り除かれる
コンテンツコレクションのスキーマは、次のようになっていました。
const column = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/column' }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
tags: z.array(z.string()).optional(),
}),
});
updatedDate がスキーマにありません。Astro のスキーマは zod で書きます。zod の z.object() は、スキーマにないキーをエラーにせず、取り除いて検証を通します。
zod だけで確かめると、次のようになります。
const { z } = require('zod');
const s = z.object({ title: z.string(), pubDate: z.date() });
const r = s.safeParse({ title: 't', pubDate: new Date(), updatedDate: new Date() });
console.log(r.success, Object.keys(r.data));
// true [ 'title', 'pubDate' ]
検証は成功します。しかし、結果から updatedDate が消えています。テンプレートで entry.data.updatedDate を読んでも、常に undefined です。
直し方:スキーマに足す
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
// 記事を大きく書き直したときに設定する。ページの表示と構造化データ(dateModified)に使う
updatedDate: z.date().optional(),
tags: z.array(z.string()).optional(),
}),
あとはテンプレートで使うだけです。
{entry.data.updatedDate && (
<time datetime={entry.data.updatedDate.toISOString()}>
{entry.data.updatedDate.toLocaleDateString('ja-JP', { year: 'numeric', month: 'long', day: 'numeric' })}
</time>
)}
SEO で困ること
今回は画面の表示だけでなく、構造化データの dateModified にも更新日を使っています。
dateModified: (updatedDate ?? pubDate).toISOString(),
updatedDate が消えていると、dateModified が黙って公開日のままになります。記事を書き直しても、検索エンジンに「更新された」と伝わりません。見た目では気づきにくく、エラーも出ないのが厄介なところです。
再発を防ぐ:未知のキーをエラーにする
書き間違い(updateDate など)も含めて気づきたい場合は、未知のキーをエラーにするスキーマにします。
// zod 4
schema: z.strictObject({ ... })
// zod 3 系
schema: z.object({ ... }).strict()
こうすると、スキーマにない項目が frontmatter にあったとき、ビルドがエラーで止まります。記事が多く、frontmatter を手で書くことが多いなら、こちらの方が安全です。
まとめ
- Astro のコンテンツコレクションでは、スキーマにない frontmatter の項目は、エラーにならずに取り除かれる(zod の
z.object()の動き) - 新しい項目を使うときは、まずスキーマに足す
- 気づける仕組みにしたいなら、
z.strictObject()で未知のキーをエラーにする
個人で開発している割り勘アプリ「WaliPro」のコラム(walipro.jp/column)で見つけた話でした。