信州大学/長野県立大学の軽音サークル「あしたぼ」の活動をオンラインで支援するフロントエンドです。Next.js 15とTypeScriptで構築されています。予約管理、動画配信、ガチャ演出など複数ドメインを一つのアプリケーションで提供します。とくに /app/booking はドメイン分離やデータフローが最も整理されているため、本ドキュメントでも重点的に紹介します。
- 目的: 音楽スタジオの予約コマ管理を中心に、バンド活動をサポートする情報発信・管理機能を提供します。
- 構成: Next.js App Router によるページ構成、ドメインごとに切り出された
/domainディレクトリ、再利用可能な UI は/shared/uiへ集約。 - 設計思想: サーバーアクションによる API 呼び出しと SWR によるクライアントキャッシュを組み合わせ、双方向なデータ更新と UX を両立します。
- フレームワーク / 言語: Next.js 15 (App Router), React 19, TypeScript 5
- スタイリング: Tailwind CSS 4, DaisyUI, カスタムコンポーネント
- フォーム / バリデーション: React Hook Form, Zod
- データ取得: SWR, Next.js Server Actions, fetch API ラッパー (
src/shared/lib/api) - UI 補助: GSAP(ガチャ演出アニメーション), MDX (ルール/告知表示)
- ユーティリティ: date-fns, React YouTube, SWR, 自前の
useFeedbackフラッシュ UI - 品質管理: Biome (lint & format), Vitest
frontend/
├─ src/
│ ├─ app/ # App Router のページ・レイアウト(サーバーコンポーネント中心)
│ │ ├─ **/page.tsx # 各ページのエントリーポイント
│ │ └─ **/_components/ # ページ固有のクライアントコンポーネント
│ │ ├─ index.tsx # ページ専用コンポーネント (page.tsx を薄く保持するためのもの)
│ │ └─ ... # その他のページ専用コンポーネント
│ ├─ domain/ # ドメイン単位のまとまり(booking, band, video など)
│ │ └─ */ui/ # ドメイン固有の共通 UI コンポーネント
│ └─ shared/ # ドメイン固有のロジック・UI(actions, hooks, service など)
│ ├─ ui/ # 共通 UI コンポーネント(ボタン、モーダル、フォーム要素など)
│ │ ├─ atoms/ # 原子コンポーネント
│ │ ├─ molecules/ # 分子コンポーネント
│ │ └─ layouts/ # レイアウトコンポーネント
│ ├─ hooks/ # 共通カスタムフック
│ ├─ lib/ # API ラッパー・フォント・R2 ストレージなどの基盤層
│ ├─ types/ # アプリ共通の型定義
│ └─ utils/ # 日付、キャッシュ制御、ロガー等のユーティリティ
├─ public/ # 画像・静的アセット
├─ package.json # スクリプトと依存ライブラリ
├─ biome.json # Biome 設定
└─ vitest.config.ts # ユニットテスト設定
src/domain/**/
├─ api/
│ ├─ **Action.ts # サーバーアクション。API 呼び出し+再検証タグ管理
│ ├─ **Fetcher.ts # SWR 用のキー生成とフェッチャー
│ └─ dto.ts # API レスポンスからドメイン型への変換
├─ constants/ # ドメイン固有定数(表示範囲・タイムスロット等)
├─ hooks/ # 週ナビゲーションや SWR ラッパー
├─ model/ # ドメインの TypeScript 型, Zod スキーマ
├─ ui/ # 画面 UI(**MainPage, **Calendar, **Create など)
└─ content/ # 使い方モーダルに表示する MDX
booking が模範的な理由:
- 役割分離が明確:
actionsでサーバーサイド処理、hooksでクライアント状態、serviceで DTO→ドメイン変換。 - キャッシュ戦略が一貫:
constantsとutils/calendarCache.tsにより SWR キャッシュと Next.js のタグ再検証を同期。 - フォーム UX: Zod + React Hook Form による型安全な入力と、
useFeedbackによるユーザー通知。 - コンテンツ管理:
booking-rule.mdxをMDXRemoteで表示し、非同期でもレイアウトを阻害しない設計。
src/app/booking/page.tsx(サーバーコンポーネント)が初期表示日とフラッシュメッセージを組み立て、MainPageLayoutとMainPageを描画。MainPage(クライアントコンポーネント)はuseBookingWeekNavigationで週単位の表示制御、useBookingCalendarDataで期間データを取得。useBookingCalendarData→buildBookingRangeKey→bookingRangeFetcher→getBookingByDateAction(サーバーアクション)という流れでバックエンド API を呼び出し、service.tsでドメイン型へ整形。- 取得した
BookingResponseはBookingCalendarがタイムスロット単位のセルへ描画し、空きコマは新規予約画面へ、既存予約は詳細ページへ誘導。 - 予約作成 (
Create.tsx)・更新・削除時にはmutateBookingCalendarsForDateで SWR キャッシュを更新し、同時にrevalidateTagで App Router のサーバーレンダリング結果も同期。 - 手動リフレッシュ (
RefreshButton) や利用ルールモーダル (MainPageLayout) が補助導線を提供。
この一連の流れにより、SSR→CSR→再検証まで一貫した UX とデータ整合性を実現しています。
- 部室予約管理 (
/booking): 週間カレンダー表示、予約作成・編集・履歴表示、パスワード認証、再検証タグを活用したリアルタイム更新。 - バンド管理 (
/domain/band): メンバー追加・編集モーダル、バンド一覧 UI。 未実装 - 動画配信 (
/domain/video): 検索フォーム、タグ編集、詳細ページ、YouTube 埋め込み。 - ガチャ演出 (
/domain/gacha): GSAP を利用したカードアニメーション、レアリティ別エフェクト、プレビュー/本番ポップアップ。 - スケジュール管理 (
/domain/schedule): スケジュール作成フォーム、サーバーアクションを使った予約連携。 - ユーザー/認証 (
/domain/user,/domain/auth): プロフィール表示やログイン周辺 UI。
- Node.js 20 以上を推奨(Next.js 15 の LTS サポート範囲)。
- 依存関係のインストール:
npm install
- 環境変数の設定:
cp .env.example .env.local.env.localに API_URL や API_KEY などを設定。 - 開発サーバー起動:
npm run dev
- 必要に応じて環境変数
NEXT_PUBLIC_APP_URLを設定(デフォルトはhttp://localhost:3000)。
npm run check: Biome による lint + format チェックnpm run lint/npm run lint:fix: lint のみ実行 / 自動修正npm run format/npm run format:fix: フォーマッターnpm run test: Vitest のユニットテストnpm run build: 本番ビルド
- ドメイン駆動の配置: ドメイン特有のロジック・UI は
src/domain/<domain>にまとめ、App Router からは必要なコンポーネントとアクションのみを公開。 - ファイル命名:
- React コンポーネント:
PascalCase.tsx - カスタムフック:
useBookingWeekNavigationのようにuse接頭辞 +camelCase - 定数:
BOOKING_VIEW_RANGE_DAYSのようにSCREAMING_SNAKE_CASE - サーバーアクション:
createBookingActionのように動詞 +Action - Zod スキーマ:
schema.tsに集約し、xxxSchemaとxxxFormValuesを併記
- React コンポーネント:
- スタイリング: Tailwind クラスを基本とし、共通レイアウトは
components/uiにある分子・原子コンポーネントで再利用。 - 型安全性: API レスポンスは
service.tsでドメイン型へ変換し、生のデータをコンポーネントに渡さない。 - 状態管理: アプリ全体でグローバルステートは極力避け、SWR とカスタムフックで局所的に管理。モーダルやフィードバックはコンポーネント単位で完結。
- Lint / Format: 変更前後で
npm run checkを実行し、Biome によるコードスタイルを維持。 - テスト: 新規ロジック追加時は
npm run testを推奨。Vitest の設定はvitest.config.tsに集約。 - サーバーアクションの再検証: 予約周りの変更では
revalidateTagとmutateBookingCalendarsForDateの呼び出し漏れに注意し、UI とサーバーキャッシュの整合性を確認。 - アクセシビリティ: SVG やモーダルなどは aria 属性を明示し、特に
/domain/bookingのカレンダーはキーボード操作でも情報が伝わるようaria-hiddenやボタン属性を利用。
この README を起点に、まずは /domain/booking のコードベースを理解すると全体の設計パターンが掴みやすくなります。他ドメインも同じ構造で拡張しやすいよう設計されています。