# Navigator サービス設計仕様書 ## 概要 Navigator(navigator.glre.dev)はボクセルベースの 3D マップサービスであり、 都市をナビゲーション可能なボクセル空間としてブラウザ上にレンダリングする。 Cloudflare Workers 上の Hono バックエンドと React フロントエンドを組み合わせ、 GLRE による GPU アクセラレーテッドインスタンスボクセルレンダリングと、 Web Worker を介した HPA\*経路探索による 3D ルート検索を実現している。 ``` Architecture Overview: ┌───────────────────────────────────────────────────────┐ │ Browser │ │ ┌─────────┐ ┌──────────┐ ┌───────────┐ ┌──────────┐ │ │ │ React │ │ Canvas │ │ Voxel │ │ HPA* │ │ │ │ UI │ │ (GLRE) │ │ Worker │ │ Worker │ │ │ └────┬────┘ └────┬─────┘ └─────┬─────┘ └─────┬────┘ │ │ │ │ │ │ │ │ └─────────┬─┴─────────────┴─────────────┘ │ │ │ SWR + Atoms │ └─────────────────┼─────────────────────────────────────┘ │ HTTPS ┌─────────────────┼──────────────────────────────────────┐ │ Cloudflare Workers │ │ ┌──────────────┴──────────────┐ │ │ │ Hono (index.tsx) │ │ │ │ ├── Auth.js (Google OAuth) │ │ │ │ ├── /api/v1/* endpoints │ │ │ │ └── /parties/* (PartyKit) │ │ │ └──────┬──────────┬───────────┘ │ │ │ │ │ │ ┌────┴───┐ ┌────┴────┐ │ │ │ D1 │ │ R2 │ │ │ │ SQLite │ │ Bucket │ │ │ └────────┘ └─────────┘ │ └────────────────────────────────────────────────────────┘ ``` ## インフラストラクチャスタック ### Cloudflare Workers ランタイム バックエンドは Cloudflare Workers 上で Hono を HTTP フレームワークとして動作する。 Vite と`@cloudflare/vite-plugin`が開発・本番ビルドの両方を担当する。 Wrangler が`vite build`後に`wrangler deploy`で Cloudflare へデプロイする。 | バインディング | 型 | 用途 | | ------------------ | -------------- | -------------------------------- | | `my_d1_navigator` | D1 Database | ユーザーデータ、履歴、リスト | | `my_r2_navigator` | R2 Bucket | ボクセルアトラスストレージ | | `v1` (PartyServer) | Durable Object | リアルタイムマルチプレイヤー状態 | ### 認証システム Google OAuth は Auth.js(`@hono/auth-js`)経由で実装されている。 DrizzleAdapter が Auth.js を D1 SQLite に接続し、セッションを永続化する。 データベースセッションではなく JWT 戦略がセッション管理に使用される。 ``` 認証フロー: ブラウザ ──→ /api/auth/signin ──→ Google OAuth ──→ コールバック ──→ JWT │ /api/v1/* ──→ verifyAuth() ミドルウェア ──→ token.sub 抽出 ──→ D1 検索 ``` Hono アプリ上の認証ミドルウェアチェーン: 1. `initAuthConfig` - Google プロバイダーと DrizzleAdapter で Auth.js を設定 2. `authHandler()` - `/api/auth/*`ルート(signin、callback、signout)を処理 3. `verifyAuth()` - `/api/v1/*`と`/parties/*`ルートを保護 4. カスタムミドルウェアが PartyServer 接続用に`x-auth-sub`ヘッダーを注入 ### リアルタイムレイヤー PartyServer(`partyserver` + `hono-party`経由)が WebSocket ベースのリアルタイム通信を提供する。 サーバークラスが接続ユーザーを追跡し、位置状態をブロードキャストする。 接続はミドルウェアが注入した`x-auth-sub`ヘッダーを通じて認証される。 ``` PartyServer ライフサイクル: onConnect(conn, ctx) ──→ subでユーザー検索 ──→ setState({ username }) onMessage(conn, msg) ──→ usersマップ更新 ──→ broadcast(JSON.stringify(users)) onClose(conn) ──→ マップから削除 ──→ broadcast(JSON.stringify(users)) ``` ## データベーススキーマ ### 既存の認証テーブル `src/schema.ts`の DrizzleAdapter が管理する。 これらのテーブルは Auth.js スキーマ規約に従う。 | テーブル | 主要カラム | | ------------------- | ----------------------------------------- | | `user` | id, name, email, emailVerified, image | | `account` | userId, provider, providerAccountId | | `session` | sessionToken, userId, expires | | `verificationToken` | identifier, token, expires | | `authenticator` | credentialID, userId, credentialPublicKey | ### アプリケーションテーブル Navigator 固有の機能のためにスキーマを拡張するテーブル群。 | テーブル | カラム | 用途 | | ---------------- | --------------------------------------------------------------- | ------------------------------ | | `search_history` | id, userId, placeId, name, address, lat, lng, searchedAt | ユーザーごとの検索履歴 | | `saved_list` | id, userId, name, icon, createdAt | ユーザー作成の場所リスト | | `saved_place` | id, listId, placeId, name, address, lat, lng, photoUrl, savedAt | 保存リスト内の場所 | | `labeled_place` | userId(PK), label(PK), placeId, name, address, lat, lng | ラベルベースの場所ブックマーク | ``` エンティティ関係: users ──1:N──→ search_history users ──1:N──→ saved_lists ──1:N──→ saved_places users ──1:N──→ labeled_places ``` ## API エンドポイント ### 認証ルート Auth.js ミドルウェアが自動的に処理する。 | メソッド | パス | 説明 | | -------- | ---------------------- | ---------------------- | | GET | `/api/auth/signin` | OAuth サインインページ | | GET | `/api/auth/callback/*` | OAuth コールバック処理 | | POST | `/api/auth/signout` | サインアウト | | GET | `/api/auth/session` | 現在のセッション情報 | ### ユーザールート | メソッド | パス | 説明 | レスポンス | | -------- | ------------ | -------------------------- | ---------------------------- | | GET | `/api/v1/me` | 現在のユーザープロフィール | `{ username, email, image }` | ### Google Maps プロキシルート サーバーサイド専用。`GOOGLE_MAPS_API_KEY`環境変数を使用して Google Maps API を呼び出し、結果をクライアントにプロキシする。 クライアントサイドコードでの API キー露出を防止する。 | メソッド | パス | クエリパラメータ | 説明 | | -------- | ----------------------------- | ---------------- | --------------------------- | | GET | `/api/v1/places/autocomplete` | `q`(文字列) | Place Autocomplete プロキシ | | GET | `/api/v1/places/geocode` | `placeId` | ジオコーディングプロキシ | ### 検索履歴ルート | メソッド | パス | ボディ / クエリ | 説明 | | -------- | ----------------- | -------------------------------------- | ---------------- | | GET | `/api/v1/history` | - | 検索履歴一覧取得 | | POST | `/api/v1/history` | `{ placeId, name, address, lat, lng }` | 履歴エントリ追加 | ### 保存リストルート | メソッド | パス | ボディ / クエリ | 説明 | | -------- | -------------------------- | ------------------ | ------------------ | | GET | `/api/v1/lists` | - | 保存リスト一覧取得 | | POST | `/api/v1/lists` | `{ name }` | 新規リスト作成 | | GET | `/api/v1/lists/:id/places` | - | リスト内の場所取得 | | POST | `/api/v1/lists/:id/places` | `{ placeId, ... }` | リストに場所を追加 | ### ラベルルート | メソッド | パス | ボディ / クエリ | 説明 | | -------- | ----------------------- | ------------------ | ----------------------- | | GET | `/api/v1/labels` | - | ラベル付き場所一覧取得 | | PUT | `/api/v1/labels/:label` | `{ placeId, ... }` | ラベルエントリ追加/更新 | ## ボクセルレンダリングシステム ### Web Mercator タイルマッピング 空間はズームレベル 17 の Web Mercator タイルに分割される。 各タイルは 256x256x256 ボクセルの Region に対応する。 SCOPE 定数が有効なタイル範囲を定義する。 ``` 座標変換パイプライン: lat/lng ──→ Web Mercator (i, j) z=17 ──→ ボクセルワールド座標 │ x = (i - SCOPE.x0 + 0.5) * 256 y = カメラ高さ z = (j - SCOPE.y0 + 0.5) * 256 ``` `canvas.tsx`の`mercator2position`関数がタイル座標をワールド空間のカメラ位置に変換する。 OFFSET 定数`[116415, 51623]`がデフォルトのカメラ中心を設定する (Web Mercator タイルにおける東京エリア付近)。 `REGION = 256`がタイルあたりのボクセル次元数である。 `hooks/useCoordConvert.ts`のユーティリティ関数が双方向変換を処理する: ``` latLngToTile(lat, lng) ──→ [i, j] z=17のWeb Mercatorタイル latLngToWorld(lat, lng) ──→ [x, y, z] ボクセルワールド座標 worldToLatLng(x, y, z) ──→ [lat, lng] 逆変換 tileToLatLng(i, j) ──→ [lat, lng] タイル中心から地理座標 ``` voxelized-js の`posOf(worldX, worldZ)`と`localOf(x, y, z, i, j)`が ワールド座標と Region ローカル座標の間の変換を行う。 ### ボクセルデータパイプライン ボクセルデータは R2 に保存されたアトラステクスチャとしてエンコードされる。 Voxel Worker(`voxel.ts`)が`voxelized-rs`(Rust WASM)経由のグリーディメッシングを実行し、 占有グリッドを描画用メッシュデータに変換する。 ``` アトラスローディング: R2 ──→ アトラス画像取得 ──→ 占有グリッドにデコード ──→ グリーディメッシュ (WASM) │ インスタンス描画コール ``` ### インスタンスレンダリングパイプライン GLRE ノードシステムがインスタンスボックスレンダリング用のシェーダーを生成する。 各ボクセルインスタンスは位置(`pos`)、スケール(`scl`)、アトラス ID(`aid`)を持つ。 Morton 曲線エンコーディングが 3D ボクセル座標を 2D アトラス UV に変換し、 `texelFetch`による色参照を行う。 ``` シェーダーパイプライン (createNode): インスタンスデータ (pos, scl, aid) │ ├── 頂点: MVP * (boxVertex * scl + pos + offset[aid]) │ └── フラグメント: texelFetch(atlas[aid], morton2uv(vCenter)) * diffuse(normal) ``` 最大 16 のアトラステクスチャ(`iAtlas0`..`iAtlas15`)と対応するオフセット (`iOffset0`..`iOffset15`)が同時にサポートされる。 ### パスレンダリング パスレンダラー(`createPath`)が HPA*の結果を色付きボックスインスタンスとして描画する。 色はインスタンスインデックスに基づいて青(出発地)から赤(目的地)に補間される。 パス位置は HPA* Worker の結果からインスタンスアトリビュートとしてアップロードされる。 ## 経路探索システム ### HPA\* アルゴリズム HPA*(Hierarchical Pathfinding A*)システムは Web Worker(`worker.ts`)内で完全に実行される。 16x16x16 サイズのクラスターに分割されたボクセル占有データ上で動作する。 ``` HPA* Pipeline: ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Load Occ │ ──→│ Build Graph │ ──→│ Abstract A* │ │ (atlas) │ │ (clusters) │ │ (high-level)│ └──────────────┘ └──────────────┘ └──────┬───────┘ │ ┌──────┴───────┐ │ Refine Path │ │ (low-level) │ └──────────────┘ ``` 1. **Region 読み込み**: タイルごとにアトラス画像から占有グリッドを読み込み 2. **グラフ構築**: クラスター境界ノードをシードし、クラスター内 BFS でエッジ重みを計算 3. **抽象探索**: 高レベルクラスターグラフ上の A\*で近似パスを発見 4. **パス精緻化**: バウンディングボックス内の低レベル BFS でボクセル精度のパスを生成 ### メモシステム Worker はグラフデータの再構築を回避するために Region ごとのメモキャッシュを保持する。 メモにはノード、エッジ、クラスター境界、構築フラグが含まれる。 メモはメインスレッドにエクスポートされ、シーンマップ上にキャッシュされ、 経路探索リクエスト間で再利用される。 ### クロス Region 経路探索 出発地と目的地が異なるタイルにある場合、Worker は以下を実行する: 1. 出発地と目的地のオフセット間の Bresenham 線上の全タイルを計算 2. 隣接接続性のために各方向に 1 タイル拡張 3. 必要な全 Region を読み込み(メモ再利用または新規アトラス取得) 4. 隣接 Region 間の境界ノードを接合 5. 全マルチ Region グラフに対して HPA\*を実行 ## フロントエンドアーキテクチャ ### コンポーネントツリー ``` App ├── Loading (初期ローディングインジケーター、メッシュ準備完了時に削除) └── PC ├── Canvas (GLRE WebGLキャンバス、ボクセル+パスレンダリング) ├── Overlay[nav] (ナビドロワー用スライドイン暗幕オーバーレイ) ├── Overlay[all] (全パネルトグルオーバーレイ) ├── Overlay[user] (ユーザーモーダルオーバーレイ) ├── PCViewerBtn (ストリートビュー開始/終了トグル) ├── PCUserModal (Googleアカウント管理モーダル) ├── PCSearch (オートコンプリートドロップダウン付き検索入力) ├── PCToolBar (左サイドバーアイコンボタン) ├── PCTabBar (メインコンテンツパネル、タブ切り替え) │ ├── PCTab1Bar (保存リスト: リスト / ラベル付き サブタブ) │ ├── PCTab2Bar (検索履歴: 日付グループ化、チェックボックス選択) │ ├── PCTab3Bar (経路検索: 出発地/目的地入力、モード選択) │ ├── PCTab4Bar (デバッグ: Mercatorグリッドビジュアライザー) │ └── PCTab5Bar (localStorageからの経路履歴) ├── PCTopBar (水平スクロール可能なトピックボタン) └── PCTopicBar (スライドインナビゲーションドロワー) ``` ### 状態管理 #### Atom システム `atoms/utils.tsx`のカスタム atom 実装が軽量なリアクティブ状態を提供する。 各 atom は値とリスナー関数の Set を保持する。 値の設定により全リスナーが同期的に通知される。 ``` Atom構造: ┌────────────┐ │ value: T │ ──→ プロパティアクセサ経由のget/set │ set: Set │ ──→ Set<(next: T) => void> リスナー └────────────┘ ``` | Atom | 型 | 用途 | | --------------------- | --------------------- | ------------------------------- | | `tabAtom` | `number` | アクティブタブインデックス(0-4) | | `modeAtom` | `number` | カメラ/移動モード | | `focusAtom` | `boolean` | 検索入力フォーカス状態 | | `userModalAtom` | `boolean` | ユーザーモーダル表示状態 | | `accountsVisibleAtom` | `boolean` | アカウントリスト切り替え | | `streetViewAtom` | `boolean` | ストリートビューモード有効 | | `goalAtom` | `[x, y, z] \| null` | HPA\*目的地座標 | | `startAtom` | `[x, y, z] \| null` | HPA\*出発地座標 | | `searchResultAtom` | `PlaceResult \| null` | 検索で選択された場所 | | `startInputAtom` | `string` | 出発地入力テキスト | | `goalInputAtom` | `string` | 目的地入力テキスト | | `startFocusAtom` | `boolean` | 出発地入力フォーカス状態 | | `goalFocusAtom` | `boolean` | 目的地入力フォーカス状態 | | `pathResultAtom` | `PathResult \| null` | 最新の経路探索結果 | | `isDebugAtom` | `boolean` | デバッグモード切り替え | `searchQueryAtom`は PCSearch コンポーネントフロー固有であるため、`atoms.ts`ではなく`anime.ts`で定義されている。 #### Render-Prop パターン React コンポーネントはフックを直接使用する代わりに、`AtomValue`と`AtomValues`の render-prop コンポーネント経由で atom を消費する。 これにより再レンダリングが render-prop 境界に隔離される。 ```tsx // 単一atom {(tab) =>
{tab}
}
// 複数atom {(tab, isFocus) =>
{tab} {isFocus}
}
``` #### SWR によるサーバー状態管理 SWR が`useSWR`フックでサーバーサイドのデータフェッチを処理する。 `useUsername`フックが`/api/v1/me`をフェッチし、 `Username`、`UserEmail`、`UserImage`の render-prop コンポーネントを提供する。 ### アニメーションシステム GSAP が`anime.ts`モジュールを通じて全 UI アニメーションを処理する。 オーバーレイの表示/非表示、パネルのスライドイン/アウト、タブ遷移が 宣言的なアニメーション関数として定義されている。 `useOverlay`フックが DOM クラスベースのイベントデリゲーションで開閉状態を管理する: - `.open-{type}` 要素が開く動作をトリガー - `.close-{type}` 要素が閉じる動作をトリガー - `.toggle-{type}` 要素がトグル動作 ### カメラと入力システム `canvas.tsx`のビューワーシステムは 2 つのモードをサポートする: | モード | 値 | 入力 | カメラ動作 | | ------ | ----- | ------------------- | --------------------------------------------- | | マップ | `-1` | ドラッグ + ホイール | トップダウンパン/ズーム、ポインターロックなし | | FPS | `0/1` | WASD + マウス | ポインターロック付き一人称歩行 | `createMode`ユーティリティが Tab キーによるウォークモード間の切り替えと Escape によるカーソル解放のモード遷移を管理する。 ホイールズームはカーソル相対ズームを使用する: カーソル下のワールド座標点が固定され、その周囲でビューポートがスケールする。 ## ファイル構成 ### ソース構造 ``` src/ ├── index.tsx Honoアプリ、認証ミドルウェア、PartyServer、APIルート ├── client.tsx Reactエントリーポイント、PCコンポーネント、ルートレンダー ├── schema.ts Drizzle ORMテーブル定義(D1 SQLite) ├── queries.ts データベースクエリ関数 ├── atoms.ts グローバルatom定義 ├── anime.ts GSAPアニメーション定義とイベントディスパッチャー ├── canvas.tsx GLREキャンバス、ボクセルビューワー、HPA*統合 ├── voxel.ts Voxel Web Worker(WASM経由グリーディメッシュ) ├── worker.ts HPA*経路探索Web Worker ├── utils.ts カメラ数学、ドラッグ/ホイール計算、モード状態 ├── atoms/ │ ├── utils.tsx atom()ファクトリ、el()、act()、stop()、push()ヘルパー │ ├── Loading.tsx 初期ローディングインジケーター │ ├── PCSearch.tsx オートコンプリートドロップダウン付き検索入力 │ ├── PCToolBar.tsx 左サイドバーアイコンナビゲーション │ ├── PCTabBar.tsx タブコンテンツパネルスイッチャー │ ├── PCTab1Bar.tsx 保存リストタブ(リスト / ラベル付き サブタブ) │ ├── PCTab2Bar.tsx 検索履歴タブ(日付グループ化、チェックボックス選択) │ ├── PCTab3Bar.tsx 経路検索タブ(出発地/目的地入力付き) │ ├── PCTab4Bar.tsx デバッグMercatorグリッドビジュアライザー │ ├── PCTab5Bar.tsx localStorageからの経路履歴 │ ├── PCTopBar.tsx 水平トピックボタンバー │ ├── PCTopicBar.tsx スライドインナビゲーションドロワー │ ├── PCUserModal.tsx Googleアカウント管理モーダル │ └── PCViewerBtn.tsx ストリートビュートグルボタン ├── hooks/ │ ├── useAtomValue.tsx Atomサブスクリプションフックとrender-propコンポーネント │ ├── useAnimation.ts GSAPアニメーションフック │ ├── useCallback.tsx 安定コールバックrefフック │ ├── useCoordConvert.ts lat/lng ↔ ボクセルワールド座標変換 │ ├── useGeocode.tsx Place IDからGoogle Maps Geocoding経由のlat/lng取得 │ ├── useLabeledPlaces.tsx ラベル付き場所(自宅、職場)のSWRフック │ ├── useListPlaces.tsx 保存リスト内場所のSWRフック │ ├── useLocalStorage.ts 経路履歴永続化 │ ├── useOverlay.tsx DOMベースのオーバーレイ開閉管理 │ ├── usePlaceSearch.tsx Google Maps Place AutocompleteのSWRフック │ ├── useSavedLists.tsx ユーザー保存リストCRUDのSWRフック │ ├── useSearchHistory.tsx 検索履歴CRUDのSWRフック │ └── useUsername.tsx render-propコンポーネント付きSWRユーザーデータフェッチ └── nodes/ ├── box.ts インスタンスボクセルレンダリング用GLREノードツリー ├── env.ts 環境マップ(HDRスカイボックス)用GLREノードツリー └── path.ts パスビジュアライゼーション用GLREノードツリー ``` ### 設定ファイル | ファイル | 用途 | | ------------------- | ------------------------------------------------------- | | `wrangler.jsonc` | Cloudflare Workers 設定(D1, R2, DO) | | `vite.config.ts` | Vite + Cloudflare プラグイン + React + Tailwind | | `drizzle.config.ts` | Drizzle Kit マイグレーション設定(SQLite ダイアレクト) | | `tsconfig.json` | TypeScript 設定 | | `package.json` | 依存関係とスクリプト | ## タブシステム タブ状態は`tabAtom`(number)で制御される。 `PCToolBar`のサイドバーボタンと`PCTopicBar`のドロワーアイテムが `anime.ts`の`tabs`配列経由でタブ変更をディスパッチする。 | タブ | コンポーネント | 機能 | ツールバーアイコン | | ---- | -------------- | ---------------------------- | ------------------ | | 0 | (デフォルト) | マップビューのみ、パネルなし | bars (メニュー) | | 1 | PCTab1Bar | 保存リストとラベル | bookmark | | 2 | PCTab2Bar | 検索履歴 | clock | | 3 | PCTab3Bar | 経路検索(出発地/目的地) | plane | | 4 | PCTab4Bar | デバッグナビゲーターグリッド | bell | `tab !== 0`の場合、`PCTabBar`パネルが左から 408px 幅でスライドインする。 パネル端のトグルボタンで全パネルを折りたたむことができる。 閉じるボタン(`.close-tab`)は`tab = 0`にリセットする。 ## 検索フロー ### 場所オートコンプリート PCSearch がユーザー入力を`/api/v1/places/autocomplete?q=...`に送信し、 サーバーサイドで Google Maps Place Autocomplete API にプロキシする。 結果が検索入力の下のドロップダウンに表示される。 ### 場所選択 場所を選択すると`/api/v1/places/geocode?placeId=...`を呼び出し、 lat/lng 座標を解決する。座標は以下の処理を経る: 1. z=17 の Web Mercator タイル(i, j)に変換 2. ボクセルワールド座標に変換 3. カメラがターゲット位置にアニメーション 4. 検索履歴エントリを D1 に永続化 ### 経路検索 PCTab3Bar が出発地と目的地のテキスト入力を提供する。 経路がリクエストされると: 1. 出発地と目的地の住所を lat/lng にジオコーディング 2. 座標をボクセルワールド座標に変換 3. `goalAtom`を設定し、`canvas.tsx`経由で HPA\* Worker をトリガー 4. Worker がパスを計算しボクセル座標を返却 5. パスがキャンバス上に色付きボックスインスタンスとしてレンダリング ## コーディング規約 ### 関数型アーキテクチャ PartyServer(partyserver ライブラリの要件)を除き class 構文を使用しない。 全ての状態管理にクロージャとファクトリ関数を使用する。 コンストラクタパターン: `const createX = (args) => { ... return { publicApi } }` ### コンポーネントパターン React コンポーネントは const アロー関数で JSX を直接返す。 ロジックを持たないコンポーネントは return 文を持たない(純粋 JSX アロー)。 フックは`hooks/`ディレクトリに分離される。 ```tsx // ロジックなしのコンポーネント - 純粋JSXアロー export const PCViewerBtn = () => ( {(isActive) => ( ... )} ) ``` ### フォーマット - 8 スペースインデント(タブを 8 スペースに展開) - 120 文字の行幅制限 - セミコロンなし - シングルクォート - アロー関数のみ(function 宣言は使用しない) ### ファイルサイズ 1 ファイルあたり約 100 行を目標とする。 単一単語のファイル名を推奨する。 複数単語の名前はディレクトリ構造の見直しが必要であることを示す。 ### インポート順序 1. 外部ライブラリ 2. プロジェクトヘルパーとユーティリティ 3. 型定義(末尾にグループ化) ### 依存パッケージ | パッケージ | 用途 | | --------------- | ------------------------------------------- | | `hono` | Cloudflare Workers 向け HTTP フレームワーク | | `drizzle-orm` | D1 SQLite 向け SQL ORM | | `react` / `swr` | UI フレームワークとサーバー状態キャッシング | | `glre` | GPU レンダリングエンジン(GLRE コア) | | `voxelized-js` | ボクセルシーン管理 | | `voxelized-rs` | グリーディメッシュ WASM モジュール | | `gsap` | アニメーションライブラリ | | `reev` | リアクティブイベントシステムとジェスチャー | | `zod` | スキーマバリデーション | | `tailwindcss` | ユーティリティファースト CSS | | `partyserver` | リアルタイム WebSocket サーバー | | `partysocket` | リアルタイム WebSocket クライアント | | `@auth/core` | Auth.js 認証 | | `@hono/auth-js` | Hono Auth.js 統合 |