ポートフォリオ
ART-HISTORIAN-ARCHIVE PUBLIC / 2026

一部の情報は非公開です。アクセスキーをお持ちの方は完全版をご覧いただけます。

呂澎(美術史家・キュレーター)

美術史家・呂澎の学術アーカイブサイト

美術史家・呂澎氏の個人サイト。Astro と Sanity で、ビルド時に 1,041 ページを生成し、実行時に CMS へは依存しません。2024 年 1 月に一人で着手し 3 月に公開、以後も保守しています。

プロジェクト概要

2024 年の初め、フリーランスとして活動していた時期に、美術史家でキュレーターの呂澎氏から個人の公式サイト制作を依頼されました。要件の整理、コンテンツのモデリング、画面デザイン、開発とデプロイまでを一人で担当し、2024 年 1 月に着手して 3 月に公開、以後も継続して保守しています。

学術アーカイブ型のサイトです。呂氏の数十年にわたる研究成果を、プロフィール・出版物・展覧会・文献・作家個別研究・教育の 6 つのセクションに整理し、トップページには最新の動きを載せています。コンテンツはすべてクライアント自身が Sanity CMS で管理でき、私が入る必要はありません。

ソースコード規模 約 7,300 行 / 82 ファイル
ビルド成果物 1,041 ページの静的 HTML

技術的な構成

サイト全体は Astro で、コンテンツは Sanity に置いています。GROQ のクエリはすべてビルド時に実行され、成果物は純粋な静的 HTML なので、実行時に CMS へアクセスすることはありません。おかげでクライアントはサーバー費用を負担せずに済み、CMS に障害が起きてもサイトが落ちることはありません。

React のアイランドは操作が必要なところにだけ使っています。展覧会のカルーセルは Swiper、画像集のライトボックスは yet-another-react-lightbox、一覧ページのホバー画像プレビューは自作です。画像集のコンポーネントはさらに IntersectionObserver で二段階の遅延読み込みにしてあり、ビューポートに入ってから実装を動的に読み込み、それまではプレースホルダーのスケルトンを表示します。

コンテンツのモデリングとリッチテキストの描画

クライアントのコンテンツは形がまちまちで、1 つのページに本文・画像集・年表・関連出版物・外部リンクが同時に入ることがあります。そこで詳細ページを組み合わせ可能なブロックの仕組みに分解しました。編集者は CMS で 8 種類のブロックを自由に並べ替えられ、フロントは種類ごとに対応するコンポーネントへ振り分けます。新しい形のコンテンツが増えても、分岐を 1 つ足すだけで済みます。

本文は Portable Text ですが、学術的な内容が求めるリッチテキストは既定の機能を超えるので、描画の層でいくつか拡張しています。

  • 学術的な脚注:本文中の記号とページ末の注釈が自動で採番され、相互に行き来できる
  • サイト内参照:CMS 上のドキュメント参照をビルド時に実際のパスへ解決する。キャッシュを持たせ、同じ参照を何度も引かない
  • 独自のマーク:太字・斜体・下線・サイト内リンク・外部リンクをそれぞれ専用のコンポーネントで描画し、リンクは内部か外部かでアイコンを出し分ける
  • 埋め込みブロック:単体画像、画像集、動画の埋め込みを本文の任意の位置に差し込める

画像処理とデプロイ

クライアントがアップロードする画像はサイズがまちまちなので、ビルド時に sharp で AVIF・WebP・JPEG の 3 形式のレスポンシブな srcset に揃えています。1 枚の変換に失敗したら自動でリトライし、それでも駄目ならその 1 枚だけを飛ばしてログに残します。壊れた画像 1 枚でビルド全体を止めないためです。

サイトは Cloudflare Workers の静的アセットホスティングにデプロイしています。あわせて sitemap に載せない内部向けのステータスページを用意し、ビルド時刻・コミットハッシュ・各コンテンツの件数を表示しています。クライアントは内容を直したあと、自分で反映を確認できます。デプロイの成否は GitHub Actions からメールで通知されます。

納品後の保守

公開後もサイトは動き続けており、必要に応じて私が保守しています。2025 年の後半には大きめの更新を 1 回入れました。Astro・Tailwind・React を当時の最新メジャーに追随させ、スタイルの層を書き直し、構造化データと SEO を補い、デプロイ先を Cloudflare Pages から Workers へ移しています。

エンジニアリング面の制約は規模に見合う範囲に留めています。Sanity のデータ構造には TypeScript の型定義を対応させ、コミット前に ESLint を自動で走らせ、ページネーションのような純粋なロジックは独立した関数に切り出してユニットテストを書きました。大きな案件ではないので、テスト体系を全面的に敷くことはしていません。

トップページ:メインビジュアルと、展覧会・出版物・文献などへの入り口
トップページ:メインビジュアルと、展覧会・出版物・文献などへの入り口
詳細ページ:組み合わせ可能なブロックで描画された本文・画像集・脚注
詳細ページ:組み合わせ可能なブロックで描画された本文・画像集・脚注
サイトを見る luhistory.com GitHub のソースコード