前回、ブログの個別のページに関して、Dynamic Route で ID を利用して作成する手順を紹介しました。今回はもう1つ改善して、URL のパスに日付と Slug を利用して処理できるように進めていきます。
コンテンツタイプの拡張
Content Hub ONE で管理する項目に Slug を追加したいと思います。ブログの URL に関して、 /blog/slug とすることでランダムな ID ではなく意味のある URL とし、キーワードを入れて運用するためです。Content Hub ONE の Blog のコンテンツタイプを開いて、以下のように Slug を追加します。この項目は必須項目としました。

続いて既存のコンテンツに対して、Slug の項目が空欄になっている部分を入力して、Content Hub ONE 側の作業を完了させます。
Interface の変更
今回はデータの構造が変わったため、ブログに関しての型定義およびクエリを管理してている interfaces/blog/index.ts のコードを書き換えます。以下のコードのように slug を追加します。
export interface Blog {
id: string;
name: string;
title: string;
description: string;
publishDate: string;
slug: string;
blogImage: {
results: Partial<Media>[];
};
}
また関連するクエリにも slug を追加してください。変更後、app/blog/[slug]/page.tsx のファイルでのデータを記述している部分を以下のように書き換えます。
return (
<div>
{post.title} :{post.publishDate} {post.slug}
</div>
);
実際に publishDate および slug が表示されます。

また、api/queries/getBlog/index.tsx でも取得したデータの処理をしています。以下の参考コードの slug の行を追加してください。
title: post.title,
slug: post.slug,
publishDate: post.publishDate,
URL に必要なデータを取得できているのを確認しました。
ID から Slug に切り替える
URL として利用していた値を ID から Slug の値に変更をします。まず、Slug を利用してブログの記事を表示するために、クエリを以下のように変更します。
export const getBlogSlugQuery = (slug: string) => {
return `query AllBlog {
allBlog(where: {slug_eq: "${slug}"}) {
total
results {
description
id
name
publishDate
slug
title
blogImage {
total
results {
id
name
description
fileHeight
fileId
fileName
fileSize
fileType
fileUrl
fileWidth
}
}
}
}
}
`;
};
上記のクエリは全てのブログの記事から Slug の値が同じものを取得する形です。このため Slug にはユニークな値を設定してください。続いて記事を取得する関数を定義している、api/queries/getBlog/index.tsx に、以下のコードを追加してください。
export async function getBlogBySlug(slug: string): Promise<Partial<Blog>> {
const results: AllBlogResponse = (await fetchGraphQL(
getBlogSlugQuery(slug)
)) as AllBlogResponse;
return results.data.allBlog.results[0];
}
なお、クエリの名前が変わっているため import で記載するクエリの名前を getBlogSlugQuery に変更してください。これで Slug を利用して該当する記事を取得することが可能となります。
では実際に slug を URL で利用するために、 app/blog/[slug]/page.tsx のファイルにてgenerateStaticParams の記述にある slug に与えている post.id を post.slug に変更してください。
export async function generateStaticParams() {
const posts = await getAllBlog();
return posts.map((post) => ({
slug: post.slug,
}));
}
またページで取得するコンテンツを以下のように変更します。
const post = await getBlogBySlug(params.slug);
これで Slug の値を利用してページを表示します。テストをしやすいように、トップページのapp/page.tsx のファイルの出力部分も以下のように変更します。
<ul>
{posts.map((post) => (
<li key={post.id}>
<a href={"/blog/" + post.slug}>
{post.title} {post.slug}
</a>
</li>
))}
</ul>
実行をすると、以下のように slug を利用してブログのページが表示されていることがわかります。

まとめ
今回は Slug として利用するフィールドを追加して URL に関して制御できるようにする手順を紹介しました。表示しているコンテンツは title だけですが、データとしては取得できているので、あとはブログのページを作ったりしていく形です。