connpass のようなイベントの掲載・申し込みができるアプリ
React Router によるクライアントサイドルーティングを実践し、SPA の実装を学ぶ。
React の実践型学習プラットフォーム React Road のお題 イベント掲載アプリに挑戦させていただいた学習プロジェクトです。
課題の実装の他、個人的な学習目的で私が行った変更や追加機能が含まれています。
Note
このリポジトリは、個人的な学習およびデモンストレーションの目的のみに使用されます。
This repository is for personal learning and demonstration purposes only.
匿名ログイン(アカウント登録不要)で気軽に申し込み・キャンセル機能を試用可能です。
|   トップページ |   イベント一覧ページ | 
|   イベント詳細ページ |   イベント作成フォーム | 
|   イベント申し込み履歴ページ |   Anonymous→本アカウント登録ダイアログ | 
- イベント一覧ページ: サイトアクセス時に、イベント一覧を表示
- イベント詳細ページ: イベント詳細情報を表示
- イベント申し込みページ: イベントに申し込むためのメールフォーム(フロントエンドのみ)
- 申し込み完了ページ: 申し込み完了メッセージを表示
- 認証システム - ユーザー登録・ログイン・ログアウト機能 #3
- イベント管理 - CRUD 操作でイベントの作成・編集・削除 #4, #17
- データベース連携 - イベントと参加者情報をデータベースに保存 #1
- 定員管理 - 参加者が満員の場合、参加できないよう制御
- 型安全性 - フロントエンドとバックエンドで型定義を共有
- モダンフォーム - React Hook Form + Zod #16
- 状態管理 - Zustand による効率的な状態管理 #29
- ルーティング - React Router v6 → v7 へのアップデート
- イベント申し込み・キャンセル機能 - 参加申し込みとキャンセル機能 #5
- Anonymous 認証 - 登録なしでゲストとしてイベント申し込みが可能、本アカウントへデータ移行も可能 #43
-  バンドルサイズ分析・最適化 - rollup -plugin-visualizer導入、チャンク分割・動的インポートによるバンドルサイズ削減・最適化 #45
- イベント作成履歴 - イベント作成履歴の表示 #40
- 画像アップロード - イベント画像のアップロード機能 #19
- ユーザー情報編集機能 - ユーザープロフィールページ・ユーザー情報の編集機能実装 #18
- イベント終了日時 - イベントの終了日時を設定 #42
- Google カレンダーに追加 - イベントを Google カレンダーに追加
- ページネーション - イベント一覧のページネーション
- イベント検索機能 - イベント検索機能
- メール通知 - メール通知システム実装 #28
| カテゴリ | 技術スタック | 
|---|---|
| フロントエンド | Vite, React, React Router v7, TailwindCSS, shadcn/ui | 
| 状態管理・フォーム | TanStack Query, Zustand, React Hook Form | 
| バリデーション | Zod(フロントエンド・バックエンド共通スキーマ) | 
| バックエンド | Cloudflare Pages Functions | 
| データベース | Turso(libSQL) | 
| 認証 | Better Auth | 
| デプロイ | Cloudflare Pages | 
| 開発ツール | TypeScript, Bun, rollup-plugin-visualizer | 
 
  Mermaid
---
config:
  theme: neo
---
graph TB
    subgraph "クライアント(ブラウザ)"
        React[React App<br/>Vite + TypeScript]
        Zustand[Zustand<br/>状態管理]
        TanStack[TanStack Query<br/>サーバー状態]
        ReactRouter[React Router v7<br/>ルーティング]
    end
    subgraph "Cloudflare Pages"
        StaticFiles[静的ファイル配信]
        Functions[Pages Functions<br/>API endpoints]
    end
    subgraph "データベース"
        Turso[(Turso libSQL)]
    end
    subgraph "認証"
        BetterAuth[Better Auth<br/>セッション管理]
    end
    React --> StaticFiles
    TanStack --> Functions
    Zustand -.-> TanStack
    Functions --> Turso
    Functions --> BetterAuth
    BetterAuth --> Turso
     
  Mermaid
---
config:
  theme: redux-color
---
erDiagram
    users {
        text id PK
        text email
        boolean emailVerified
        text name
        text image
        boolean isAnonymous
        integer createdAt
        integer updatedAt
    }
    events {
        text id PK
        text title
        text date
        text location
        text description
        text image_url
        integer capacity
        text creator_id FK
        integer created_at
    }
    attendees {
        text id PK
        text event_id FK
        text email
        text user_id FK
        integer created_at
    }
    sessions {
        text id PK
        text userId FK
        text token
        integer expiresAt
        text ipAddress
        text userAgent
        integer createdAt
        integer updatedAt
    }
    accounts {
        text id PK
        text accountId
        text providerId
        text userId FK
        text accessToken
        text refreshToken
        text idToken
        text password
        integer createdAt
        integer updatedAt
    }
    verifications {
        text id PK
        text identifier
        text value
        integer expiresAt
        integer createdAt
        integer updatedAt
    }
    users ||--o{ events : creates
    users ||--o{ attendees : registers
    users ||--o{ sessions : has
    users ||--o{ accounts : has
    events ||--o{ attendees : has
     
  Mermaid
---
config:
  theme: redux-color
---
sequenceDiagram
    participant U as User
    participant C as Component
    participant Z as Zustand Store
    participant T as TanStack Query
    participant A as Better Auth API
    participant D as Database
    U->>C: ログインボタンクリック
    C->>T: authClient.signIn.email()
    T->>A: Better Auth認証
    A->>D: ユーザー認証・セッション作成
    D-->>A: 認証結果
    A-->>T: レスポンス返却
    T->>Z: ユーザー情報を更新
    Z-->>C: 状態変更通知
    C-->>U: UI更新
    | エンドポイント | メソッド | 認証 | 説明 | 
|---|---|---|---|
| /api/events | GET | - | イベント一覧取得 | 
| /api/events/[id] | GET | - | イベント詳細取得 | 
| /api/events/create | POST | ✅ | イベント作成 | 
| /api/events/[id]/update | PUT | ✅ | イベント更新 | 
| /api/events/[id]/delete | DELETE | ✅ | イベント削除 | 
| エンドポイント | メソッド | 認証 | 説明 | 
|---|---|---|---|
| /api/events/[id]/apply | POST | ✅ | イベント申し込み | 
| /api/events/[id]/cancel | DELETE | ✅ | イベント申し込みキャンセル | 
| /api/user/registrations | GET | ✅ | ユーザー申し込み履歴取得 | 
| /api/user/created-events | GET | ✅ | ユーザーイベント作成履歴取得 | 
Better Auth による統一認証エンドポイント(Email and Password)
| エンドポイント | メソッド | 認証 | 説明 | 
|---|---|---|---|
| /api/auth/sign-in/email | POST | - | ユーザーログイン | 
| /api/auth/sign-up/email | POST | - | ユーザー新規登録 | 
| /api/auth/sign-out | POST | ✅ | ユーザーログアウト | 
| /api/auth/get-session | GET | - | セッション情報取得 | 
Note: Better Auth の [[catchall]] ハンドラーにより、認証関連のエンドポイントは自動的に提供される。
| エンドポイント | メソッド | 認証 | 説明 | 
|---|---|---|---|
| /api/upload/image | POST | ✅ | 汎用画像アップロード | 
| /api/upload/image | DELETE | ✅ | 画像削除 | 
| /api/upload/image | GET | ✅ | ユーザー画像一覧取得 | 
- 登録なしで即体験: 面倒な会員登録なしでイベントの閲覧・申し込みが可能
- 一時的なデータ保存: 申し込み履歴は匿名ユーザー ID で一時保存
- スムーズなアップグレード: ワンクリックで正規ユーザーに移行
 
  Mermaid
graph LR
    A[ゲストユーザー] --> B[イベント申し込み]
    B --> C[一時データ保存]
    C --> D[アカウント作成]
    D --> E[データ自動移行]
    E --> F[正規ユーザー]
    style A fill:#e1f5fe
    style F fill:#e8f5e8
    style E fill:#fff3e0
    - ✅ イベント申し込み履歴
- ✅ ユーザー設定・preferences
- ✅ セッション情報
- Node.js: 22.16.0 (.nvmrc で指定)
- パッケージマネージャー: bun
- TypeScript: ^5.7.2
# フロントエンド (Vite)
bun run dev
# バックエンド (Wrangler + Vite)
bunx wrangler pages dev -- bun run dev# ビルド
bun run build
# プレビュー
bun run preview- rollup-plugin-visualizer によるバンドルサイズ分析
- チャンク分割: React、Router、Form ライブラリを個別バンドル化
- 遅延読み込み: React.lazy() によるイベント作成画面の動的インポート
- 成果: 初期バンドルサイズ 29%削減(647KB → 460KB)
# バンドル分析実行
bun run build:analyze