Next.js App Routerで展覧会一覧ページを作る【Art Navi開発記録 #2】
はじめに
こんにちは。
なかのひとカンパニーの archer です。
前回の記事では、美術展検索サービス Art Navi を作り始めた背景や、技術構成について書きました。
- サービスURL: https://art-weekend.jp/
今回は、Art Navi の中心機能のひとつである 展覧会一覧ページ についてまとめます。
この記事は、自分の開発内容を整理するための備忘録も兼ねています。
今回作るもの
今回作るのは、展覧会を一覧で表示するページです。
Art Navi では、以下のページが該当します。
/exhibitions
このページでは、開催中・開催予定の展覧会をカード形式で表示します。
MVP段階では、まず以下の情報を表示する方針にしました。
- 展覧会名
- 会場名
- エリア
- 開催期間
- ジャンル
- 簡単な説明
- 詳細ページへのリンク
最初から検索機能や複雑な絞り込みを作り込むのではなく、まずは一覧として見られる状態を優先しました。
App Routerでページを作る
Next.js App Router では、URLに対応するディレクトリを app 配下に作ります。
展覧会一覧ページの場合は、以下のような構成です。
app/
exhibitions/
page.tsx
app/exhibitions/page.tsx を作ることで、
/exhibitions にアクセスしたときのページになります。
シンプルな構成にすると、以下のようなイメージです。
// app/exhibitions/page.tsx
import Link from "next/link";
const exhibitions = [
{
id: 1,
title: "印象派と光の表現",
venue: "上野の美術館",
area: "上野",
period: "2026年6月1日〜2026年8月31日",
genre: "西洋美術",
description: "印象派の作品を中心に、光の表現に注目した展覧会です。",
},
{
id: 2,
title: "現代アートの現在地",
venue: "六本木の美術館",
area: "六本木",
period: "2026年7月1日〜2026年9月15日",
genre: "現代アート",
description: "国内外の現代アート作品を紹介する展覧会です。",
},
];
export default function ExhibitionsPage() {
return (
<main>
<h1>展覧会一覧</h1>
<div>
{exhibitions.map((exhibition) => (
<article key={exhibition.id}>
<h2>{exhibition.title}</h2>
<p>{exhibition.venue}</p>
<p>{exhibition.area}</p>
<p>{exhibition.period}</p>
<p>{exhibition.genre}</p>
<p>{exhibition.description}</p>
<Link href={`/exhibitions/${exhibition.id}`}>
詳細を見る
</Link>
</article>
))}
</div>
</main>
);
}
最初はこのように固定データでも問題ありません。
MVPでは、まず画面の構成や導線を確認することを優先しました。
カード形式で表示する
一覧ページでは、展覧会をカード形式で表示するようにしました。
カード形式にした理由は、スマホでも見やすく、情報の区切りが分かりやすいからです。
表示する内容は、最初から増やしすぎないようにしました。
展覧会名
会場名
エリア
開催期間
概要
詳細リンク
一覧ページで情報を詰め込みすぎると、逆に見づらくなります。
そのため、詳しい説明は詳細ページに持たせ、一覧では「気になるかどうか判断できる情報」だけを表示する方針にしました。
詳細ページへのリンク
展覧会一覧から詳細ページへ移動できるようにします。
App Router では、動的ルーティングを使って以下のようなURLを作れます。
/exhibitions/1
/exhibitions/2
/exhibitions/3
ディレクトリ構成は以下です。
app/
exhibitions/
page.tsx
[id]/
page.tsx
一覧ページ側では、next/link を使って詳細ページへのリンクを作ります。
<Link href={`/exhibitions/${exhibition.id}`}>
詳細を見る
</Link>
これで、展覧会ごとの詳細ページへ遷移できます。
ジャンル絞り込みについて
MVPでは、ジャンルによる絞り込みも想定しています。
URLは以下のような形にしました。
/exhibitions?genreId=1
検索条件をURLのクエリパラメータに持たせることで、ページを共有しやすくなります。
たとえば、特定ジャンルの展覧会一覧をそのままURLとして共有できます。
実装イメージは以下です。
type SearchParams = {
genreId?: string;
};
export default function ExhibitionsPage({
searchParams,
}: {
searchParams: SearchParams;
}) {
const genreId = searchParams.genreId;
const filteredExhibitions = genreId
? exhibitions.filter((exhibition) => String(exhibition.genreId) === genreId)
: exhibitions;
return (
<main>
<h1>展覧会一覧</h1>
{filteredExhibitions.map((exhibition) => (
<article key={exhibition.id}>
<h2>{exhibition.title}</h2>
</article>
))}
</main>
);
}
まずはシンプルに、genreId がある場合だけ絞り込む形にしています。
実装時に意識したこと
展覧会一覧ページでは、以下を意識しました。
- スマホで見やすいこと
- 一覧で情報を出しすぎないこと
- 詳細ページへの導線を分かりやすくすること
- URLで絞り込み状態を表現できること
- 後からDB連携しやすい形にすること
特に、後からデータ取得元を差し替えやすくすることは意識しました。
最初は固定データでも、後でPostgreSQLから取得する形に変更できるように、表示部分とデータ取得部分をなるべく分ける方針にしています。
今後やりたいこと
展覧会一覧ページについては、今後以下を改善していきたいです。
- エリアでの絞り込み
- 開催中・開催予定の絞り込み
- 表示順の変更
- 検索キーワード対応
- お気に入りボタンの追加
- DBからのデータ取得
- SEO向けの一覧ページ強化
まずはシンプルな一覧ページを作り、そこから少しずつ機能を追加していく予定です。
まとめ
今回は、Art Navi の展覧会一覧ページについてまとめました。
Next.js App Router では、app/exhibitions/page.tsx を作ることで、簡単に /exhibitions ページを用意できます。
MVP段階では、最初から複雑な検索や絞り込みを作り込むのではなく、まずは以下を優先しました。
- 展覧会を一覧で見られること
- 詳細ページへ移動できること
- ジャンル絞り込みの土台を作ること
- 後からDB連携しやすい形にすること
次回は、認証なしで使えるお気に入り機能について書く予定です。