はじめに
皆さんこんにちは!ふぉくしーど (@foxseed2314) です!
普段は「たからーん」名義で記事を投稿していますが、今回は「ふぉくしーど」としての技術活動について解説します。同一人物です。
この記事では、VRChatで開催したバーチャルイベント「バーチャルケモナイト」のLP制作において、企画段階の思考から技術選定、設計、そして運用まで、プロジェクトの裏側を詳細に解説します。
「バーチャルケモナイト」は、2025年7月12日(土)に有志で開催されたオールナイトのバーチャルDJイベントです。
ケモナー(※)と、音楽イベントファンをターゲットとし、約120匹もの方々にご来場いただきました。大きなトラブルもなく、参加者に心から楽しめるような音楽体験を提供できたと考えています。
※人間的な特徴を見せる動物キャラである「ケモノ」のファン
イベントのLPはイベント後も公開しており、オープンソースとしてソースコードも公開しています。
LP制作を行う決断をした背景
VRChatの有志イベントでは、告知は「VRChatイベントカレンダー」への掲載や、知人のワールドへのポスター設置に留まるのが一般的で、専用のLPが制作されるケースは稀です。
しかし、今回のイベントは主催の「VRChatに触れていないケモナーの人にVRChatに触れてみてほしい」という強い想いから始まりました。我々のイベント組織は設立されたばかりで知名度が低かったため、VRChat外で影響力のある著名なゲストを招待し、集客力を高める必要がありました。
そこで、信頼性の高い情報発信拠点としてLPを制作する決断をしました。SNSよりも網羅的かつ正確な情報を提供することで、イベントの魅力を伝え、Webからの集客にもつなげることができると考えたためです。
目的の洗い出し
LP制作に取り掛かる前に、「なぜLPを作るのか」を洗い出しました。クオリティや規模感にもよりますが、LP制作は数か月かけて作成するもので、かなり工数を要するものです。間違った道に進まないためにも、LPの目的を明確にしておくことが重要です。
目的
- イベントの告知
- タイムスケジュール伝えやすくする
- スタッフのクレジットを載せる
- Ko-fiでの寄付の案内をするため(インゲージメント上げるため)
スケジュールの決定
イベント開催日は7月12日(土)。オールナイト開催という性質上、参加者がスケジュールを確保できるよう、遅くとも2か月前には告知を開始する必要がありました。また、運営費の寄付を募るため、LPは3か月前には公開したいという目標がありました。
プロジェクトが開始されたのは2月末。残された期間は約4か月です。
著名なゲストを招待する以上、それにふさわしい品質のLPが求められます。しかし、開発リソースは限られており、デザイン、実装、インフラ構築、運用のすべてを僕1人で担当する必要がありました。
これらの制約から、4月後半のリリースを目標とし、本業に支障が出ない範囲で2か月間の開発期間を設定しました。
要件定義
せっかく大きなイベントのLP制作を担当させていただくので、技術チャレンジ要素も入れたいものです。
技術チャレンジ要素を考えるため、LPを見るユーザー視点と運用するユーザー視点のそれぞれの機能要件と、非機能要件を洗い出しました。
技術選定
上で挙げた機能要件と非機能要件を満たす技術やサービスを選定しました。個人的にはここが一番楽しかったです。ここが運用費0円を実現するための重要なポイントです。
- Figma(UIデザインツール)
直感的な操作で、細部までUIデザインを作成できるのが強いです。プロトタイピング機能を用いることで、Webサイトのプレビューを関係者に配布できる点から採用しました。
- microCMS(CMS)
日本製のヘッドレスCMSで、コンテンツ管理画面、コンテンツDB、APIを提供するSaaSです。GUIから追加した情報をすぐにAPIで取ってこれる利便性と、データ構造を自由に設計できる、しかも無料で!という点から採用しました。
- Cursor(AIコードエディタ)
VSCodeをフォークしたAIコードエディタです。今はGitHub CopilotやClaude Code、Kiroなどのエージェントがありますが、Cursorは複雑なコンテキストを理解する能力に長けています。AIと対話しながらサクッとコードを生成してほしかったので、Cursorをメインで利用していました。
- GitHub(バージョン管理)
開発に必要な機能が一通り揃っていて、すぐに環境を準備できるので利用しています。
- TypeScript(プログラミング言語)
今回はすべてフロントエンドで完結するので、言語はTypeScriptで統一しています。今はTSが当たり前すぎて他に語ることはありません。
- Astro(フレームワーク)
高速なページ表示を目指すため、SSG(静的サイト生成)に優れたAstroを選定しました。ReactやVueなどのコンポーネントも統合可能で、将来的な拡張性も確保できる点を評価しました。
- Tailwind CSS(CSSフレームワーク)
僕が一番慣れているフレームワークです。ユーティリティファーストな設計により、AIによる補完との相性が良く、レスポンシブデザインを効率的に実装できるため選定しました。
- Motion (Framer Motion)(アニメーションライブラリ)
世界観を演出しつつ、パフォーマンスを損なわない軽量なアニメーションを実装するため選定しました。GSAPほどリッチな機能は不要と判断し、バンドルサイズの軽さを重視しました。
- Swiper(スライダーライブラリ)
カルーセルUIを実装するための、デファクトスタンダードなライブラリであるため選定しました。
- Day.js(日付ライブラリ)
安全に日時情報やタイムゾーンを扱うため。非推奨となったMoment.jsの代替として、バンドルサイズが軽量なDay.jsを選定しました。
- React(UIライブラリ)
MotionやSwiperといったライブラリの利用や、インタラクティブで複雑なUIを実装するため、Astroのアイランドアーキテクチャを介して部分的に利用しました。基本的にアニメーションがかかるコンポーネントはすべてReactで実装しています。
- react-use(Reactライブラリ)
ブラウザAPI(ウィンドウサイズ、スクロール位置取得など)を宣言的かつ安全に利用するために選定しました。
- Astro SEO(SEOライブラリ)
SEOに不可欠なメタタグを型安全に生成し、管理を容易にするために選定しました。
- Astro SEO Schema (Astro JSON-LD Schema)(SEOライブラリ)
Google検索結果でのリッチリザルト表示を目的とし、構造化データを容易に生成するために選定しました。構造化データを入れることで、SEO最適化の効果が期待できます。
- Astro Sitemap(サイトマップライブラリ)
クローラーの巡回を促進し、SEO効果を最大化するためにサイトマップを自動生成するために選定しました。
- Google Analytics(アナリティクス)
ページのアナリティクス(閲覧数や訪問元など)を確認するために利用しています。データの信頼性が高く、業界標準のアクセス解析ツールです。BigQueryとの連携も容易な点を評価しました。
- Astro Partytown(パフォーマンスライブラリ)
Google Analyticsのような3rd partyのスクリプトは、ページの読み込みを遅くします。Partytownを利用することで、そのようなスクリプトをWeb Workerに再配置し、メインスレッドから開放できます。
- Terser(圧縮ツール)
コードのMinify(圧縮)を行うために利用しています。フレームワークでAstroを使っているので、中のViteがうまいことMinifyしてくれますが、より細かなチューニングを行うためにTerserを利用しています。
- Biome(Linter/Formatter)
Rust製で高速に動作し、設定もシンプルなため選定しました。ESLint/Prettierの代替として、開発効率の向上を目的としています。
- Playwright MCP(テストライブラリ)
AIによるUI実装補助や、プロンプトベースでのアクセシビリティ検証を自動化し、品質保証の効率を高めるために選定しました。
- Cloudflare Pages(ホスティング)
Webページのホスティングサービスです。手厚い無料枠、GitHub連携による容易なCI/CD、そして *.pages.dev
という可読性の高いドメインを利用できるので選定しました。
Cloudflareの @yusukebe 氏は「理由がない限りCloudflare PagesではなくCloudflare Workersを使ってほしい」と述べています。今回は *.pages.dev
ドメインの分かりやすさを優先し、Pagesを選定しました。
- Cloudflare R2(ストレージ)
microCMSの無料枠では扱えない動画アセットの保存先として選定しました。Cloudflare PagesからのEgressが無料であり、高い親和性を持つためでもあります。
- BigQuery(データ分析)
Google Analyticsの生データをより高度に分析するために利用しています。GA4からの自動エクスポート機能により、容易にデータパイプラインを構築できる点を評価しました。
ページデザイン戦略
UIデザインはすべてFigmaで作成しました。開発メンバーが1人という状況下で速度を最優先するため、コンポーネントやオートレイアウトといった厳密な設計は行わず、アイデアを即座に形にすることを重視しました。
Figmaの便利なところは、組んだデザインをすぐに関係者にプロトタイプとして共有できるところです。
運営メンバーとの定例会議前にさくっとデザインを組んで、定例中にプロトタイプを各デバイスから触ってもらって、改善を行う〜というループができます。
また、OGPや告知画像なども同一のFigmaプロジェクトで管理することで、デザインアセットの一元管理と編集の効率化を図りました。
ディレクトリ設計
今回のプロジェクトでは、ファイル種別ごとのコロケーションと機能単位での関心事の分離のバランスを取ったディレクトリ構成を採用しました。直感的で慣れ親しんだフォルダ構造により、数か月後にコードを見返しても「どこに何があるか」がすぐに理解できる設計です。
.
├── .cursor/
│ ├── mcp.json # MCPの設定
│ ├── prompts/ # Cursorで実行するプロンプト指示書
│ └── rules/ # Cursor Rules
├── .gitignore
├── .node-version
├── .vscode/
│ ├── extensions.json
│ └── settings.json
├── astro.config.mjs # Astroの設定
├── biome.jsonc # Biomeの設定
├── LICENSE
├── package.json
├── public/
│ ├── fonts/ # WOFF2形式のフォント
│ └── ...
├── README.md
├── src/
│ ├── components/ # Atomic Design ベースの UI
│ ├── layouts/ # ページ全体の枠組み
│ ├── libs/ # ドメインロジック & 共通ユーティリティ
│ │ ├── analytics/ # Google Analytics関連
│ │ ├── animations/ # 汎用アニメーション
│ │ ├── stores/ # microCMSのデータストア
│ │ └── utils/ # 共通ユーティリティ
│ ├── pages/ # Astro ルーティング
│ └── styles/ # Tailwind CSS設定
├── tsconfig.json # TypeScriptの設定
└── wrangler.toml # Cloudflareの設定
ポイント
-
直感的な構造
-
components/
にUI、libs/
にロジックを配置する伝統的な構成は、プロジェクトの全体像を即座に把握するのに役立ちます。
-
-
機能的な凝集性
-
libs/stores/
やlibs/analytics/
のように機能ごとにファイルをまとめることで、関連する改修を単一のディレクトリ内で完結させ、見通しを良くしています。
-
-
親しみやすいデザインパターン
- File-Type Colocationを基本としつつ、
utils/
やanalytics/
ではModule Patternのように機能を名前空間化。これにより、直感性と構造化を両立させています。
- File-Type Colocationを基本としつつ、
掲載する情報だけでなく、イベントにまつわる情報をCMSで一元管理
LPには、パフォーマーの自己紹介やソーシャルリンク、出演時間などを掲載しますが、LP制作開始時点ではあまり定まっていませんでした。これらの情報をスプシで管理するのが一般的ですが、変更があるたびにLPのコードを変更するのは面倒です。そこで、イベントにまつわる情報をCMSで管理し、自動的にLPに反映できる仕組みを構築しました。
そこで考慮するべきなのは、どのCMSを使うかです。
microCMS | WordPress | Contentful | Newt | Strapi | |
---|---|---|---|---|---|
アーキテクチャ | Headless | Traditional | Headless | Headless | Headless |
ホスティング | マネージド | 自前 or マネージド | マネージド | マネージド (※2026年11月サービス終了予定) | 自前 or クラウド |
データ構造の柔軟性 | 高い (APIベースで自由に定義) | 中~高 (カスタム投稿タイプ、プラグインで拡張) | 高い (コンテンツモデルで自由に定義) | 高い (コンテンツモデルで自由に定義) | 高い (APIベースで自由に定義、自社でカスタマイズ可能) |
価格 | 無料プランあり | 無料プランあり (WordPress.comの場合)、自前運用はサーバー費用等 | 無料プランあり | 無料プランあり (※2026年11月サービス終了予定) | 無料プランあり (Community Edition), 有料 (Cloud / Enterprise) |
日本語ドキュメント/サポート | 非常に充実 | 非常に充実 (コミュニティ含む) | 比較的充実 (日本語情報も多い) | 充実 (※2026年11月サービス終了予定) | 比較的充実 (コミュニティ中心) |
コミュニティの規模 | 国内では大きい | 世界最大級 | 世界的に大きい | 国内では大きい (※サービス終了アナウンスあり) | 世界的に大きい |
画像最適化機能 | あり (APIで操作) | プラグインで対応 | あり (APIで操作) | あり (Assets API, 外部CDN連携) | あり (プラグイン/外部サービス連携) |
サクッと使い始めたいのと、面倒な運用を避けたい、でもデータ構造を柔軟に編集したい!欲を言えば僕以外の運営もデータを編集できるようにしたい!という思いから microCMS を選定しました。
使いやすいGUIでデータを編集できます。
Astro × microCMS × Cloudflare Pages でJamstack構成を実現
今回のLP制作では、高速な表示と高いセキュリティを実現するため、Jamstack構成を採用しました。
Jamstackとは、JavaScript、API、Markupの頭文字を取ったアーキテクチャです。事前にビルドされた静的なHTML/CSS/JSファイルをCDNから配信します。ユーザーアクセス時にサーバーでページを生成する従来方式と異なり、以下のメリットがあります。
- パフォーマンス: 静的ファイルのため表示が極めて高速。
- 可用性: CDNから配信するため、アクセス集中に強い。
- セキュリティ: サーバーサイドの攻撃対象領域が少ない。
この構成を実現するため、ヘッドレスCMSの microCMS とSSG(静的サイトジェネレータ)の Astro、ホスティングサービスの Cloudflare Pages を組み合わせました。
この3つを組み合わせることで、コンテンツの更新は手軽に行いつつ、ユーザーには最適化された高速なページを届けるという、運用性とパフォーマンスの両立を実現しました。
データ構造
microCMSはデータ構造を柔軟に定義できる点が強みです。当時の無料プランではAPIが3つまでという制約があったため(現在は5つまで)、関連データを1つのAPIエンドポイントに集約して管理しました。
以下のような構造でデータを管理しています。
AIによる不適切コンテンツのチェック
多くの出演者やゲストの情報をLPに載せるため、不適切な表現や誤解を招く記述は絶対に避けなければなりません。また、アクセシビリティの担保も重要な品質要件です。
そこで、これらの品質チェックを自動化・効率化するため、AI(Cursor)を活用したレビュー体制を構築しました。事前にチェック項目を指示書(プロンプト)としてMarkdownで定義し、定期的にAIエージェントに実行させることで、人的ミスを防ぎ、品質を担保しました。
指示書例1:スマートフォン向けのアクセシビリティチェック
LPの主要な目的は情報伝達であり、特にモバイルデバイスからのアクセスが容易であることは不可欠です。以下の指示書は、視覚的なアクセシビリティを検証するプロンプトです。
CursorでPlaywright MCPを利用できるように設定し、視覚的なチェックを可能にしています。
あなたはシニアWebフロントエンドエンジニアで、アクセシビリティが重視された軽量なLP制作に長けています。
■ このアプリの概要や技術など
.cursor/rules/global.mdc を参照してください。
■ タスク
これは大物ゲストの情報が載ったDJイベントのLPです。
Pixel 7 (412 x 915)環境でのユーザーがページをコントロールする際のアクセシビリティを評価してください。特に以下の点に注目します:
1. タッチ操作アクセシビリティ(モバイル特有)
- タッチターゲットのサイズは十分か(最低44x44px推奨)
- タッチ要素間の間隔は適切か
- スワイプやピンチなどのジェスチャー操作は直感的か
- タッチフィードバックは明確か
- Android TalkBackでのナビゲーションは適切か
- タッチ操作に依存しない代替手段が提供されているか
- 画面の回転(縦横切り替え)に対応しているか
2. スクロール操作(モバイル特有)
- 縦スクロールの操作感は自然か
- 横スクロールが必要な要素はPixel 7の画面幅(412px)で適切に表示されるか
- スクロールによる情報の表示/非表示は適切か
- スクロール位置の把握が容易か
- スムーススクロールの実装はAndroidのアニメーション設定と調和しているか
- 固定ヘッダー/フッターがある場合、コンテンツを隠していないか
3. 色のコントラストとビジュアル
- Pixel 7のディスプレイ特性を考慮したテキストと背景のコントラスト比はWCAG AAレベル(4.5:1)以上か
- 大きなテキストのコントラスト比はWCAG AAレベル(3:1)以上か
- タップ状態や操作状態の視覚的フィードバックはPixel 7の画面で十分か
- 色だけに依存した情報伝達を避けているか
- Androidのダークモード使用時の表示は適切か
- フォントサイズはPixel 7の画面で読みやすいか
4. モバイル特有の考慮事項
- ソフトキーボードが表示された際のレイアウト調整は適切か
- 通知バーやナビゲーションバーとの干渉はないか
- バッテリー消費に影響するアニメーションや処理は最適化されているか
- オフライン状態での動作や通知は適切か
- モバイルデータ使用量への配慮はあるか
■ 手順
1. Pixel 7 (412 x 915)環境で実際にタッチ操作でページを操作し、全ての機能にアクセスできるか確認する
2. Android TalkBackを使用してスクリーンリーダーでの操作性を確認する
3. Androidのコントラストチェッカーを使用して色のコントラスト比を検証する
4. 縦横両方の画面向きでテストを行う
5. 発見した問題点と改善提案をまとめる
■ ARIA属性
適切なARIA属性の使用状況も評価してください。特に:
- aria-hidden
- aria-label
- aria-labelledby
- aria-describedby
- aria-live
- aria-expanded
- aria-controls
などの使用がPixel 7環境で適切か確認してください。
指示書例2:言語表現のチェック
今回のイベントのターゲット層は、ジェンダーなどの多様性に対する関心が高い傾向があります。そのため、無意識な差別的表現や誤解を招く言葉を排除することが極めて重要です。
あなたはシニアWebフロントエンドエンジニアで、アクセシビリティが重視された軽量なLP制作に長けています。
■ このアプリの概要や技術など
.cursor/rules/global.mdc を参照してください。
■ タスク
これは大物ゲストの情報が載ったDJイベントのLPです。
サイトに書かれている内容の言語使用について評価してください。特に以下の点に注目します:
1. 読みやすさ
- 文章の長さは適切か
- 専門用語や業界用語は適切に説明されているか
- 文法や表現は正確か
- 句読点の使用は適切か
- 段落分けは論理的か
2. 明確さと誤解のなさ
- 曖昧な表現はないか
- 誤解を招く可能性のある表現はないか
- 情報は正確に伝わるか
- 重要な情報が欠けていないか
- 矛盾する情報はないか
3. 包括性と配慮
- 差別的な表現はないか
- 特定の集団を排除するような言葉遣いはないか
- ジェンダー中立的な言葉が適切に使用されているか
- 文化的に配慮した表現が使われているか
- 不快感を与える可能性のある表現はないか
4. イベント情報の明確さ
- 日時、場所、料金などの重要情報は明確か
- ゲスト情報は適切に紹介されているか
- イベントの目的や内容が明確に伝わるか
- 参加方法や注意事項は分かりやすく説明されているか
- 問い合わせ先は明確に記載されているか
■ 手順
1. サイト全体のテキストコンテンツを確認する
2. 上記の評価基準に基づいて分析する
3. 問題点を特定し、具体的な改善提案を行う
4. 特に優れている点も指摘する
5. 全体的な言語使用の評価をまとめる
■ 評価レポート形式
1. 全体評価(概要)
2. 読みやすさの評価
3. 明確さと誤解のなさの評価
4. 包括性と配慮の評価
5. イベント情報の明確さの評価
6. 具体的な改善提案
7. 総括
その他の指示書はリポジトリで公開していますので、ぜひ参考にしてください。
良かった点
運用費0円で妥協がないLP運用体制を作れた
CloudflareとmicroCMSの無料枠を最大限に活用し、サーバーレスでスケーラブルなインフラをコストゼロで実現しました。
CMSに情報を一元管理したおかげで、ページへの反映が非常にやりやすかった
更新頻度の高い情報をmicroCMSに集約したことで、コードに触れることなく迅速な情報更新が可能になり、運用負荷が大幅に軽減されました。
AIの便利なところを活用した開発ができた
コーディングはもちろんですが、今回はコンテンツのチェックの部分でもAIを活用してみました。
AIはオペレーション業務の自動化が得意です。
Playwright MCPを活用することにより、1人開発でありながら、アクセシビリティや表現の配慮といった多角的な品質担保を実現できました。
改善したい点
ディレクトリ構成は改善余地があるかも
今回採用した構成はLPとして十分機能しますが、改善点としてコンポーネントの粒度設計が挙げられます。例えば、Atomic Designのような考え方を取り入れてコンポーネントをより細かく分割しておけば、ABテストや部分的なデザイン変更といった、LP特有の素早いイテレーションにさらに対応しやすくなったかもしれません。
まとめ
本記事では、AstroとmicroCMSを用いて構築した、運用費0円のバーチャルイベントLPの技術的裏側を紹介しました。
「目的の定義 → 要件定義 → 技術選定」 というプロセスを丁寧に行うことで、品質を担保しつつ、コストを抑えたスピーディな開発を実現できたと考えています。また、AIを開発プロセスに積極的に組み込むことで、1人開発というリソースの制約の中でも、多角的な視点での品質向上と技術的挑戦が可能になりました。
当然今回の技術選定と設計は、数か月後には反省点が多く見つかると思います。しかし、常に 「なぜその技術を選ぶのか」という意思決定の理由 を持ち、小さなサイクルで振り返りと改善を繰り返すことが、価値を迅速に提供し続けるための鍵だと考えています。
余談
今回のQiitaの記事は Gemini CLI に添削してもらいました。
Geminiは処理できるコンテキストの量が多いからか、他のコーディングエージェントと比べて、文章作成の質が高いと感じています。