目次
はじめに
前回は、AstroとヘッドレスCMS「NILTO」を連携させて、ブログ記事の一覧ページを作成しました。
今回はその続きとして、URLの一部となるスラッグ(slug)をNILTOの入力ルール機能で管理し、Astroの動的ルーティング機能を使って、記事ごとの個別ページを自動で生成する方法を紹介します。
スラッグ(slug)とは?
スラッグとは、URLの一部として使われる、そのページの内容を分かりやすく表した文字列のことです。
(例) https://example.com/blog/astro-tutorial-1 このURLの astro-tutorial-1 の部分がスラッグにあたります。
スラッグを適切に設定すると、以下のようなメリットがあります。
- ユーザーにとって: URLを見るだけで、どんな内容のページか推測しやすくなります。
- 検索エンジンにとって:ページの内容を理解しやすくなり、SEO(検索エンジン最適化)の観点からも有利になります。
NILTOでモデル・コンテンツを準備する
前回作成した「ブログ記事」モデルに、スラッグを管理するための専用フィールドを追加し、コンテンツを更新します。

チュートリアル
2025-06-02T08:53:11Z
「スラッグ用フィールド」を追加して入力ルールを設定する
NILTOの管理画面で、前回作成した「ブログ記事」モデルの編集画面を開き、以下の手順でフィールドを追加します。
フィールドタイプの選択と基本設定
- フィールドタイプとして「1行テキスト」を選択します。
- 以下の通りに設定します。
- フィールド名: スラッグ
- LUID: slug

エラーを防ぐための入力ルール設定
入力ルールを厳格に設定して、意図しないURLが作られるのを防ぎます。
- 必須にする: 「必須にする」を選択します。(入力漏れを防ぎます)
- 重複を禁止する: 「はい」を選択します。(同じURLのページが作られるのを防ぎます)
- 入力ルール: 「正規表現」を選択し、以下の通り入力します。
- 正規表現: ^[a-z0-9-]+$(この設定により、入力できる文字が「半角英小文字、数字、ハイフン」のみに制限されます)
- 正規表現: ^[a-z0-9-]+$(この設定により、入力できる文字が「半角英小文字、数字、ハイフン」のみに制限されます)
- 最後に「保存」ボタンをクリックして、フィールドを追加します。

コンテンツを更新して公開する
- 前回作成したブログ記事の編集画面を開きます。
- 新しく追加された「スラッグ」フィールドに、URLにしたい文字列(例:my-first-post)を入力します。
- コンテンツを「公開」します。

(補足)重複を禁止する設定の確認
試しに、別の記事で先ほどと同じスラッグ(my-first-post)を入力して公開してみてください。「重複禁止の値が含まれているため、公開できません」というエラーメッセージが表示され、公開できません。このように、NILTOの機能でURLの一意性を担保できます。

Astroでスラッグを元に個別の記事ページを作成する
NILTOで準備したスラッグを使って、Astroで記事ごとの詳細ページを生成します。
前回作成したブログサイト用のAstroプロジェクトにコードを追加していきます。
動的ルートファイルを作成する
Astroプロジェクトの src/pages/blog/ ディレクトリ内に、 [slug].astro という名前で新しいファイルを作成します。
ファイルパス: src/pages/blog/[slug].astro
この [slug] という書き方が、Astroの動的ルーティングの仕組みです。NILTOにあるスラッグの数だけ、自動的にページが作られます。
getStaticPaths でNILTOからデータを取得する
作成した [slug].astro ファイルに、以下のコードを記述します。このコードは、ビルド時にNILTOから全記事のデータを取得し、どのページを生成するかをAstroに伝えます。
// src/pages/blog/[slug].astro
---
import Layout from '../../layouts/Layout.astro';
import { getContents } from '../../lib/getContents.js';
export async function getStaticPaths() {
const { contents } = await getContents(); // 全記事データを取得
// 各記事に対してページを生成するための情報を返す
// params のキー (ここでは 'slug') はファイル名 `[slug].astro` と一致させる
return contents.map((content: any) => {
return {
params: { slug: content.slug }, // URLのパスパラメータとして使用
props: { content }, // ページコンポーネントに記事データ全体を渡す
};
});
}
// getStaticPaths の props で渡された content を取得
const { content } = Astro.props;
---
<!-- ここから下にページの見た目(HTML)を書いていく -->
ページコンポーネントで記事を表示する
最後に、getStaticPaths の下(--- の外側)に、ページの見た目となるHTMLを記述します。Astro.props を使って、前のステップで渡された記事データを表示します。
// (上のコードの続き)
const { post } = Astro.props;
---
<Layout title={content.title}>
<article>
<h1>{content.title}</h1>
<p>
<small
>公開日: {
content._published_at
? new Date(content._published_at).toLocaleDateString()
: '未公開'
}</small
>
</p>
<div class='content-body'>
{
(
<div set:html={content.article} /> // set:html にフレキシブルテキストの内容をセット
)
}
</div>
<a href='/'>← NILTOブログ一覧へ戻る</a>
</article>
</Layout>
<style>
article {
padding: 20px;
max-width: 720px;
margin: 0 auto;
}
h1 {
margin-bottom: 0.5em;
font-size: 2.2em;
}
.content-body {
margin-top: 2em;
margin-bottom: 2em;
line-height: 1.7;
}
.content-body p,
.content-body ul,
.content-body ol {
margin-bottom: 1em;
}
.content-body h2 {
font-size: 1.8em;
margin-top: 1.5em;
margin-bottom: 0.7em;
}
.content-body h3 {
font-size: 1.5em;
margin-top: 1.2em;
margin-bottom: 0.6em;
}
</style>
これで設定は完了です。開発サーバーを起動して http://localhost:4321/blog/my-first-post のようなURLにアクセスし、記事の詳細ページが表示されることを確認してみましょう。
さいごに
今回は、NILTOでスラッグを管理し、Astroの動的ルーティング機能を使って個別の記事ページを作成しました。
NILTOの入力ルールとAstroのページ生成機能を組み合わせることで、エラーが少なく、管理しやすいブログサイトを構築できます。