このブログはAstroで作っています。セットアップの手順と、いくつかはまったところをメモしておきます。

Astroとは

Astro は静的サイトジェネレーターです。特徴的なのは「Islands Architecture」という考え方で、基本的にはHTMLを出力しつつ、必要な部分だけにJavaScriptを適用できます。

ブログのような、インタラクションが少ないサイトには特に向いていると思います。

セットアップ

npm create astro@latest

プロジェクトを作成したら、必要なインテグレーションを追加します。

npx astro add mdx sitemap
  • @astrojs/mdx: MarkdownにJSXコンポーネントを埋め込めるようにする
  • @astrojs/sitemap: サイトマップを自動生成する

コンテンツコレクション

Astroにはコンテンツコレクションという仕組みがあって、src/content/ 以下のファイルをスキーマで管理できます。

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const posts = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string(),
    date: z.coerce.date(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
});

export const collections = { posts };

z.coerce.date() を使っておくと、フロントマターに date: 2026-03-19 と書いてもDateオブジェクトとして受け取れます。

記事一覧の取得

import { getCollection } from 'astro:content';

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

getCollection の第二引数にフィルター関数を渡せます。draft: true の記事を除外するのに便利。

シンタックスハイライト

AstroはShikiを内蔵しているので、設定するだけで使えます。

// astro.config.mjs
export default defineConfig({
  markdown: {
    shikiConfig: {
      themes: {
        light: 'github-light',
        dark: 'github-dark',
      },
      wrap: true,
    },
  },
});

ライト/ダークテーマを両方指定しておくと、CSSの prefers-color-scheme に合わせて自動で切り替わります。

全文検索(Pagefind)

Pagefind はビルド後の静的ファイルを解析してインデックスを作成するツールです。サーバーが不要なので静的サイトとの相性が良いです。

{
  "scripts": {
    "build": "astro build && npx pagefind --site dist"
  }
}

ビルド後に npx pagefind を実行するだけでインデックスが生成されます。あとは検索ページでUIを初期化するだけ。

<link rel="stylesheet" href="/pagefind/pagefind-ui.css" />
<div id="search"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
  new PagefindUI({ element: '#search', showImages: false });
</script>

はまったところ

getStaticPaths の戻り値

タグページを動的に生成するときに getStaticPaths が必要ですが、props に渡した値は同じファイル内で型推論が効かないことがあります。明示的に型を書いたほうが安全です。

コレクションのslugとURL

getCollection で取得したエントリの slug はファイル名から自動で生成されます(hello-world.mdhello-world)。URLとの対応を意識しておくと混乱しません。


全体的にドキュメントが充実していて、詰まったときも公式サイトで大体解決できました。Astroはおすすめです。