Skip to content
Cloud AI エンジニア入門ガイド
Go back

05. AstroPaperで記事を書く:フロントマターと公開制御

この章の全体像として、必須の3項目、検証の仕組み、日時の書き方、公開の判定の4つを番号順に並べ、書いた記事が意図どおり公開されるようになることを示した図

シリーズ目次 前章: 04. astro-paper.config.ts で設定する 次章: 06. AstroPaperで記事を整理する:ディレクトリ・URL・タグ

Table of contents

Open Table of contents

この章のねらい

AstroPaperで記事を書く作業は、src/content/posts/ にMarkdownファイルを足すだけです。ただしファイル先頭のフロントマターには書き方の決まりがあります。全項目と、公開・非公開を制御する仕組みを見ていきます。

最初の1本を書く

src/content/posts/hello-world.md を作り、次の内容を書きます。

---
title: "はじめての記事"
description: "AstroPaperで最初の記事を書いてみます。"
pubDatetime: 2026-08-02T09:00:00.000Z
tags:
  - "日記"
---

ここから本文が始まります。

## 見出し

Markdownの記法がそのまま使えます。src/content/posts/hello-world.md

開発サーバーを起動していれば、これだけで /posts/hello-world/ に記事が表示されます。

フロントマターとは

ファイル先頭を --- で挟んだ部分がフロントマターです。ここに記事の属性(タイトル、日付、タグなど)をYAMLという形式で書きます。

YAMLは キー: 値 の形で書く設定用の記法です。階層は字下げで表し、配列は行頭の - で表します。

title: "記事タイトル"
tags:
  - "タグ1"
  - "タグ2"

書ける項目の一覧

項目必須既定値説明
title文字列記事タイトル。ページのH1見出しになる
description文字列記事の要約。一覧・SEO・OGPに使われる
pubDatetime日時公開日時
modDatetime日時なし更新日時
author文字列サイトの author著者名
featured真偽値falseトップページの「Featured」に載せる
draft真偽値false下書きにする
tags文字列の配列["others"]タグ
ogImage画像またはURL自動生成SNS共有用の画像
canonicalURL文字列自動生成正規URL
hideEditPost真偽値falseこの記事だけ編集リンクを隠す
timezone文字列サイトの timezoneこの記事だけタイムゾーンを変える

必須は titledescriptionpubDatetime の3つだけ。残りは省略したときに何が入るかさえ知っていれば、書く量はぐっと減ります。

必須のtitle・description・pubDatetimeの3項目と、省略すると既定値が入る9つの任意項目を左右に分けて並べた図

検証の仕組み

フロントマターの形式は src/content.config.ts で定義されています。

const posts = defineCollection({
  loader: glob({ pattern: "**/[^_]*.{md,mdx}", base: "./src/content/posts" }),
  schema: ({ image }) =>
    z.object({
      author: z.string().default(config.site.author),
      pubDatetime: z.date(),
      modDatetime: z.date().optional().nullable(),
      title: z.string(),
      tags: z.array(z.string()).default(["others"]),
      description: z.string(),
      // ...
    }),
});src/content.config.ts

ここで使われている zZod というライブラリです。この項目は文字列、この項目は日付、と形を宣言しておくと、条件を満たさない記事があったときにビルドが落ちて、どのファイルのどの項目が問題なのかを教えてくれます。

たとえば pubDatetime を書き忘れると、次のようなエラーが出ます。

[InvalidContentEntryDataError] posts → hello-world data does not match collection schema.
pubDatetime: Required

書式の誤りを公開前に必ず捕まえられる。これがREADMEにある type-safe markdown(型安全なMarkdown)の中身です。

検証は記事が公開される手前に置かれていて、通れば公開、通らなければビルドが止まります。

記事のフロントマターがcontent.config.tsのZodスキーマに照らされ、形が合えば公開、合わなければビルド失敗となる流れを示した図

.default() の意味

authortags には .default(...) が付いています。書かなかった場合に自動で入る値です。author を省略すればサイト設定の著者名が、tags を省略すれば ["others"] が入ります。

日時の書き方

pubDatetime はYAMLが日時として解釈できる形で書きます。ISO 8601形式が確実です。

pubDatetime: 2026-08-02T09:00:00.000Z

末尾の Z は協定世界時(UTC)を意味します。この値が、設定した timezone に変換されて画面に表示されます。

書いた値timezone: "Asia/Tokyo" での表示
2026-08-02T09:00:00.000Z2 Aug, 2026(日本時間 18:00)
2026-08-02T20:00:00.000Z3 Aug, 2026(日本時間 翌 05:00)

日本時間で書きたい場合は、オフセットを明示することもできます。

pubDatetime: 2026-08-02T18:00:00+09:00

日時を引用符で囲むと文字列として扱われ、日付型を期待するスキーマと合わずにエラーになります。日時には引用符を付けないと覚えてください。逆に titledescription は、コロンなどがYAMLの区切り記号と衝突しないよう、常に引用符で囲むのが安全です。

書いた値と画面に出る値がずれるのは、この変換をはさんでいるためです。

協定世界時で書いた日時が、Asia/Tokyoの設定によって9時間ずれた表示になる2つの例と、引用符の扱いを示した図

modDatetime の効果

modDatetime を書くと、記事一覧の並び順が更新日時基準になり、日付表示も「Updated」に変わります。

new Date(b.data.modDatetime ?? b.data.pubDatetime).getTime()src/utils/getSortedPosts.ts

?? は、左が未設定なら右を使うという記法です。modDatetime があればそれを、なければ pubDatetime を使って並べ替えます。

記事を大きく書き直したときに modDatetime を足せば、一覧の先頭へ戻せます。

公開されるかどうかの判定

記事が一覧に出るかどうかは、次の順序で決まります。

ファイル名・下書き設定・実行環境・公開日時から記事の表示可否が決まる流れを示したフロー図

判定の本体は src/utils/postFilter.ts です。

export function postFilter({ data }: CollectionEntry<"posts">) {
  const isPublishTimePassed =
    Date.now() >
    new Date(data.pubDatetime).getTime() - config.posts.scheduledPostMargin;
  return !data.draft && (import.meta.env.DEV || isPublishTimePassed);
}src/utils/postFilter.ts

読み解くと次のようになります。

  1. draft: true の記事は、いつでも除外される
  2. 開発サーバー(import.meta.env.DEV が真)では、下書き以外はすべて表示される
  3. 本番ビルドでは、公開日時から猶予を引いた時刻を過ぎているものだけ表示される

下書き

draft: true

書きかけの記事はこれで隠せます。開発サーバーでも一覧に出なくなるので、確認したいときは一時的に false にしてください。

予約公開

未来の日時を pubDatetime に設定すると、その時刻まで公開されません。

pubDatetime: 2026-09-01T00:00:00.000Z

ただしAstroPaperは静的サイトなので、時刻が来ても勝手には公開されません。公開されるのは、その時刻を過ぎた後にビルドしたときです。予定どおりに出したいなら、ホスティングサービスの定期ビルド機能などを使ってください。

scheduledPostMargin(既定15分)は、この判定を少し前倒しにする猶予でした。00:00公開の記事を23:50のビルドに含めたい、といった場面で効きます。

_ で始まるファイルの扱い

src/content.config.ts の取り込みパターンは **/[^_]*.{md,mdx} です。[^_]_ 以外の文字で始まるという条件なので、_draft.md のようなファイルは記事として認識されません。

ここで引っかかります。この条件が効くのはファイル名だけです。パターン先頭の **/ はディレクトリ名を問わないので、_notes/memo.md のように _ 付きディレクトリの中にある _ なしのファイルは、そのまま取り込まれます。しかもURLを組み立てる際に _ で始まるディレクトリは読み飛ばされるので、/posts/memo/ として公開されます。

除外したいMarkdownには、ディレクトリではなくファイル名の先頭_ を付けてください。なお画像やSVGは .md / .mdx ではないため最初から対象外で、assets/ のようなディレクトリに分けるだけで十分です。

注目記事

featured: true

これを付けた記事は、トップページのFeatured欄に出ます。同時にRecent Postsからは外れるので、両方に重複して並ぶことはありません。

代表作や自己紹介の記事を固定表示したいときに使います。

トップページ上で置き場所が入れ替わる、と考えてください。

featured trueを書いた記事が、トップページのFeatured欄へ移り、Recent Posts欄からは外れることを示した図

タグ

tags:
  - "Astro"
  - "初心者向け"

タグを付けると、/tags/ の一覧と /tags/<タグ名>/ の絞り込みページが自動で作られます。日本語のタグも使えます。タグとURLの関係は次章: 06. AstroPaperで記事を整理する:ディレクトリ・URL・タグで扱います。

記事ごとの上書き設定

サイト全体の設定を、特定の記事だけ変えたいときに使う項目です。

項目用途
author寄稿記事など、著者が違う場合
timezone現地時間で書いた記事の日付を正しく見せたい場合
canonicalURL他サイトに掲載した記事の転載である場合
hideEditPost編集リンクを出したくない記事がある場合
ogImage自動生成ではなく専用の画像を使いたい場合

canonicalURL は入れておいてください。同じ内容が複数のURLに存在すると検索評価が分散するため、「本来の掲載場所はこちら」と宣言することで正しく集約されます。

テンプレート

新しい記事を書き始めるときのひな形として、次をコピーすると迷いません。

---
title: ""
description: ""
pubDatetime: 2026-08-02T09:00:00.000Z
featured: false
draft: true
tags:
  - ""
---

## 見出し

本文

draft: true から始めて、完成したら false に変える。この運用にしておけば、書きかけを公開する事故は起きません。

要点

参考資料


シリーズ目次 前章: 04. astro-paper.config.ts で設定する 次章: 06. AstroPaperで記事を整理する:ディレクトリ・URL・タグ


Share this post:

Previous Post
06. AstroPaperで記事を整理する:ディレクトリ・URL・タグ
Next Post
04. astro-paper.config.ts で設定する