@squadbase/vantage 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +24 -4
  2. package/dist/{chunk-ZGDU5YLH.js → chunk-5L2MH2NG.js} +16 -7
  3. package/dist/chunk-5L2MH2NG.js.map +1 -0
  4. package/dist/chunk-7IPAXPPY.js +51 -0
  5. package/dist/chunk-7IPAXPPY.js.map +1 -0
  6. package/dist/chunk-A2UUGASH.js +12 -0
  7. package/dist/chunk-A2UUGASH.js.map +1 -0
  8. package/dist/chunk-DTDVSFRY.js +29 -0
  9. package/dist/chunk-DTDVSFRY.js.map +1 -0
  10. package/dist/chunk-WQZYXXQW.js +2249 -0
  11. package/dist/chunk-WQZYXXQW.js.map +1 -0
  12. package/dist/{chunk-73J5ZD4C.js → chunk-YLAB6UQS.js} +17 -3
  13. package/dist/chunk-YLAB6UQS.js.map +1 -0
  14. package/dist/cli.js +607 -36
  15. package/dist/cli.js.map +1 -1
  16. package/dist/client/index.d.ts +2 -1
  17. package/dist/client/index.js +3 -1
  18. package/dist/client/index.js.map +1 -1
  19. package/dist/components/index.d.ts +575 -0
  20. package/dist/components/index.js +2097 -0
  21. package/dist/components/index.js.map +1 -0
  22. package/dist/{define-page-B6y9TOfZ.d.ts → define-page-BfhrK99G.d.ts} +5 -0
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/markdown/index.d.ts +9 -0
  27. package/dist/markdown/index.js +26 -0
  28. package/dist/markdown/index.js.map +1 -0
  29. package/dist/query/index.d.ts +95 -2
  30. package/dist/query/index.js +102 -1
  31. package/dist/query/index.js.map +1 -1
  32. package/dist/router/index.d.ts +86 -1
  33. package/dist/router/index.js +71 -7
  34. package/dist/router/index.js.map +1 -1
  35. package/dist/server/node.js +6 -1
  36. package/dist/server/node.js.map +1 -1
  37. package/dist/ui/index.d.ts +316 -200
  38. package/dist/ui/index.js +566 -511
  39. package/dist/ui/index.js.map +1 -1
  40. package/dist/vite/index.js +2 -2
  41. package/docs/en/agent-skills.md +89 -0
  42. package/docs/en/api-and-server.md +84 -0
  43. package/docs/en/build-and-deploy.md +280 -0
  44. package/docs/en/cli-reference.md +311 -0
  45. package/docs/en/components.md +235 -0
  46. package/docs/en/data-fetching.md +142 -0
  47. package/docs/en/environment-variables.md +69 -0
  48. package/docs/en/getting-started.md +95 -0
  49. package/docs/en/index.md +65 -0
  50. package/docs/en/markdown/markdown-renderer.md +44 -0
  51. package/docs/en/pages-and-metadata.md +59 -0
  52. package/docs/en/parts/app-shell.md +54 -0
  53. package/docs/en/parts/dashboard-card.md +64 -0
  54. package/docs/en/parts/data-table.md +86 -0
  55. package/docs/en/parts/date-range-picker.md +41 -0
  56. package/docs/en/parts/echart.md +53 -0
  57. package/docs/en/parts/filter-bar.md +66 -0
  58. package/docs/en/parts/funnel-steps.md +33 -0
  59. package/docs/en/parts/metric-value.md +23 -0
  60. package/docs/en/parts/multi-select.md +27 -0
  61. package/docs/en/parts/page-shell.md +45 -0
  62. package/docs/en/parts/placeholder.md +38 -0
  63. package/docs/en/parts/searchable-select.md +47 -0
  64. package/docs/en/parts/section-header.md +20 -0
  65. package/docs/en/parts/segmented-control.md +25 -0
  66. package/docs/en/parts/sparkline.md +47 -0
  67. package/docs/en/parts/status-badge.md +44 -0
  68. package/docs/en/parts/trend-indicator.md +26 -0
  69. package/docs/en/routing.md +177 -0
  70. package/docs/en/ui/accordion.md +36 -0
  71. package/docs/en/ui/alert.md +31 -0
  72. package/docs/en/ui/badge.md +23 -0
  73. package/docs/en/ui/breadcrumb.md +38 -0
  74. package/docs/en/ui/button.md +39 -0
  75. package/docs/en/ui/calendar.md +28 -0
  76. package/docs/en/ui/card.md +35 -0
  77. package/docs/en/ui/checkbox.md +34 -0
  78. package/docs/en/ui/cn.md +34 -0
  79. package/docs/en/ui/collapsible.md +21 -0
  80. package/docs/en/ui/command.md +37 -0
  81. package/docs/en/ui/dialog.md +52 -0
  82. package/docs/en/ui/dropdown-menu.md +50 -0
  83. package/docs/en/ui/empty.md +22 -0
  84. package/docs/en/ui/error-state.md +50 -0
  85. package/docs/en/ui/input-group.md +30 -0
  86. package/docs/en/ui/input.md +28 -0
  87. package/docs/en/ui/label.md +19 -0
  88. package/docs/en/ui/loading.md +19 -0
  89. package/docs/en/ui/popover.md +34 -0
  90. package/docs/en/ui/progress.md +28 -0
  91. package/docs/en/ui/scroll-area.md +23 -0
  92. package/docs/en/ui/select.md +63 -0
  93. package/docs/en/ui/separator.md +15 -0
  94. package/docs/en/ui/sheet.md +28 -0
  95. package/docs/en/ui/sidebar.md +92 -0
  96. package/docs/en/ui/skeleton.md +16 -0
  97. package/docs/en/ui/slider.md +21 -0
  98. package/docs/en/ui/spinner.md +14 -0
  99. package/docs/en/ui/switch.md +19 -0
  100. package/docs/en/ui/table.md +24 -0
  101. package/docs/en/ui/tabs.md +23 -0
  102. package/docs/en/ui/textarea.md +15 -0
  103. package/docs/en/ui/toggle-group.md +26 -0
  104. package/docs/en/ui/toggle.md +19 -0
  105. package/docs/en/ui/tooltip.md +22 -0
  106. package/docs/en/ui/use-is-mobile.md +18 -0
  107. package/docs/en/ui-and-theming.md +95 -0
  108. package/docs/index.json +1346 -0
  109. package/docs/ja/agent-skills.md +87 -0
  110. package/docs/ja/api-and-server.md +84 -0
  111. package/docs/ja/build-and-deploy.md +279 -0
  112. package/docs/ja/cli-reference.md +305 -0
  113. package/docs/ja/components.md +231 -0
  114. package/docs/ja/data-fetching.md +142 -0
  115. package/docs/ja/environment-variables.md +68 -0
  116. package/docs/ja/getting-started.md +95 -0
  117. package/docs/ja/index.md +65 -0
  118. package/docs/ja/markdown/markdown-renderer.md +43 -0
  119. package/docs/ja/pages-and-metadata.md +59 -0
  120. package/docs/ja/parts/app-shell.md +54 -0
  121. package/docs/ja/parts/dashboard-card.md +64 -0
  122. package/docs/ja/parts/data-table.md +85 -0
  123. package/docs/ja/parts/date-range-picker.md +41 -0
  124. package/docs/ja/parts/echart.md +52 -0
  125. package/docs/ja/parts/filter-bar.md +64 -0
  126. package/docs/ja/parts/funnel-steps.md +33 -0
  127. package/docs/ja/parts/metric-value.md +25 -0
  128. package/docs/ja/parts/multi-select.md +27 -0
  129. package/docs/ja/parts/page-shell.md +45 -0
  130. package/docs/ja/parts/placeholder.md +37 -0
  131. package/docs/ja/parts/searchable-select.md +47 -0
  132. package/docs/ja/parts/section-header.md +20 -0
  133. package/docs/ja/parts/segmented-control.md +26 -0
  134. package/docs/ja/parts/sparkline.md +47 -0
  135. package/docs/ja/parts/status-badge.md +44 -0
  136. package/docs/ja/parts/trend-indicator.md +26 -0
  137. package/docs/ja/routing.md +175 -0
  138. package/docs/ja/ui/accordion.md +37 -0
  139. package/docs/ja/ui/alert.md +31 -0
  140. package/docs/ja/ui/badge.md +23 -0
  141. package/docs/ja/ui/breadcrumb.md +38 -0
  142. package/docs/ja/ui/button.md +39 -0
  143. package/docs/ja/ui/calendar.md +28 -0
  144. package/docs/ja/ui/card.md +35 -0
  145. package/docs/ja/ui/checkbox.md +34 -0
  146. package/docs/ja/ui/cn.md +34 -0
  147. package/docs/ja/ui/collapsible.md +21 -0
  148. package/docs/ja/ui/command.md +36 -0
  149. package/docs/ja/ui/dialog.md +51 -0
  150. package/docs/ja/ui/dropdown-menu.md +50 -0
  151. package/docs/ja/ui/empty.md +22 -0
  152. package/docs/ja/ui/error-state.md +50 -0
  153. package/docs/ja/ui/input-group.md +30 -0
  154. package/docs/ja/ui/input.md +28 -0
  155. package/docs/ja/ui/label.md +19 -0
  156. package/docs/ja/ui/loading.md +19 -0
  157. package/docs/ja/ui/popover.md +34 -0
  158. package/docs/ja/ui/progress.md +28 -0
  159. package/docs/ja/ui/scroll-area.md +24 -0
  160. package/docs/ja/ui/select.md +64 -0
  161. package/docs/ja/ui/separator.md +15 -0
  162. package/docs/ja/ui/sheet.md +28 -0
  163. package/docs/ja/ui/sidebar.md +92 -0
  164. package/docs/ja/ui/skeleton.md +16 -0
  165. package/docs/ja/ui/slider.md +21 -0
  166. package/docs/ja/ui/spinner.md +14 -0
  167. package/docs/ja/ui/switch.md +19 -0
  168. package/docs/ja/ui/table.md +24 -0
  169. package/docs/ja/ui/tabs.md +24 -0
  170. package/docs/ja/ui/textarea.md +15 -0
  171. package/docs/ja/ui/toggle-group.md +27 -0
  172. package/docs/ja/ui/toggle.md +19 -0
  173. package/docs/ja/ui/tooltip.md +22 -0
  174. package/docs/ja/ui/use-is-mobile.md +18 -0
  175. package/docs/ja/ui-and-theming.md +95 -0
  176. package/package.json +29 -4
  177. package/registry/blocks/sales-overview.tsx +43 -19
  178. package/registry/ui/data-table.tsx +702 -102
  179. package/skills/vantage-add-feature/SKILL.md +153 -0
  180. package/skills/vantage-app/SKILL.md +291 -0
  181. package/skills/vantage-pitfalls/SKILL.md +139 -0
  182. package/templates/AGENTS.md +313 -0
  183. package/theme.css +178 -40
  184. package/dist/chunk-73J5ZD4C.js.map +0 -1
  185. package/dist/chunk-ATYZ45XL.js +0 -19
  186. package/dist/chunk-ATYZ45XL.js.map +0 -1
  187. package/dist/chunk-ZGDU5YLH.js.map +0 -1
@@ -0,0 +1,87 @@
1
+ # エージェントと Skills
2
+
3
+ > Vantage に同梱された Claude Code の Agent Skills。vantage add skill でアプリの .claude/skills/ に配置し、エージェントに手順を伴うワークフローを教える。
4
+
5
+ Vantage は **Claude Code の Agent Skills** を同梱しています。Skill は「手順を伴うワークフロー」を、
6
+ エージェントが必要なときだけ呼び出せる形にしたものです。UI キットや CLI の使い方といった
7
+ 静的な参照(このドキュメント)とは別に、**再現可能な段取り**をエージェントに渡すのが目的です。
8
+
9
+ ## 何が同梱されているか
10
+
11
+ いずれも「Vantage **アプリを作るエージェント**」向けの手順です。
12
+
13
+ | skill | 扱う手順 |
14
+ |---|---|
15
+ | `vantage-app` | アプリの新規作成と、`index.tsx` 単体の SPA から `server/api`・ネストレイアウト・動的ルート・404/error を備えた fullstack への拡張 |
16
+ | `vantage-add-feature` | ページ / API / UI / ブロックの追加(`vantage add` + `check` / `routes` までの一連) |
17
+ | `vantage-pitfalls` | 落とし穴リファレンス(Base UI ≠ Radix、`SelectValue` の挙動、クライアントから `server/` を import しない など) |
18
+
19
+ ## 配置する
20
+
21
+ Skill のソースは `@squadbase/vantage` パッケージに同梱されています。`vantage add skill` で、
22
+ 対象アプリの `.claude/skills/` にコピーします。
23
+
24
+ ```bash
25
+ vantage add skill --all # 同梱スキルをすべて配置
26
+ vantage add skill vantage-app # 名前を指定して1つだけ配置
27
+ vantage add skill vantage-app --force # 既存を上書き
28
+ ```
29
+
30
+ 配置後のレイアウト:
31
+
32
+ ```text
33
+ your-app/
34
+ ├── index.tsx
35
+ ├── package.json
36
+ └── .claude/
37
+ └── skills/
38
+ ├── vantage-app/SKILL.md
39
+ ├── vantage-add-feature/SKILL.md
40
+ └── vantage-pitfalls/SKILL.md
41
+ ```
42
+
43
+ `.claude/skills/` は Claude Code が自動で認識します。エージェントはタスクに応じて、対応する
44
+ Skill の手順を読み込んで実行します。
45
+
46
+ > [!NOTE]
47
+ > `.claude/` はツール用の設定であり、アプリのコードではありません。`vantage check` の静的診断は
48
+ > このディレクトリを走査しないため、置いてもビルドや検査には影響しません。
49
+
50
+ ## 配布と更新の方針
51
+
52
+ - **source-of-truth はパッケージ内**にあります。Skill はフレームワークのバージョンと一緒に
53
+ 配布・更新されるため、`@squadbase/vantage` を上げれば最新の手順が手に入ります。配置済みの
54
+ コピーを更新したいときは `vantage add skill --all --force` を実行します。
55
+ - **Squadbase テンプレートには配置済み**です。テンプレートから作ったアプリには、最初から
56
+ `.claude/skills/` が入っています。手で作ったアプリには `vantage add skill` で足してください。
57
+
58
+ ## `AGENTS.md`(アプリの地図)
59
+
60
+ Skill が「手順書」なら、`AGENTS.md` は**エージェントが最初に読む「地図」**です。Vantage の
61
+ 不変条件・import サブパスの地図・ルーティング規約・データ取得/API/env の最小レシピを 1 ページに
62
+ まとめてあり、**それだけ読んで最小アプリを組める**ことを狙っています。手順の深掘りは上の Skill へ
63
+ 名前で誘導し、内容は重複させません。
64
+
65
+ Skill と同じく **source-of-truth はパッケージ内**にあり、`vantage add agents` でアプリルートへ
66
+ 配置します。
67
+
68
+ ```bash
69
+ vantage add agents # AGENTS.md をアプリルートに配置
70
+ vantage add agents --force # 既存を上書き
71
+ ```
72
+
73
+ 配置済みの `AGENTS.md` は `vantage upgrade` で正本と同期されます(差分があるときだけ書き換え、
74
+ まだ配置していないアプリには作りません)。フレームワークの規約が変わっても、**正本 1 箇所の更新**が
75
+ `upgrade` でアプリへ反映されます。Squadbase テンプレートには最初から配置済みです。
76
+
77
+ ## 責務の切り分け
78
+
79
+ Skill は「**手順を伴うワークフロー**」だけを担います。次のものとは役割を分け、内容を重複させません。
80
+
81
+ - **このドキュメント**(仕様・リファレンス)― 何がどう動くかの静的な説明。ブラウザを開けない
82
+ エージェントには、同じ内容が [`vantage docs`](cli-reference) でそのまま読めます
83
+ (`vantage docs button` で props の表、`vantage docs --json` で機械可読。名前が
84
+ 分からなければ `vantage search <やりたいこと>`)。
85
+ - **`AGENTS.md`**(静的な地図)― 構成やファイルの居場所。`vantage add agents` で配置します。
86
+ - Skill 同士 ― 落とし穴などの共通内容は各 Skill に写経せず、**名前で相互参照**します
87
+ (例: `vantage-app` の手順中から `vantage-pitfalls` を指す)。
@@ -0,0 +1,84 @@
1
+ # API とサーバー
2
+
3
+ > server/ を足すと API が有効になる。ApiContext・HttpError・HTTP メソッドの規約。
4
+
5
+ Vantage の**サーバーはオプション**です。プロジェクトに `server/` ディレクトリを追加すると
6
+ API が有効になり、ビルドは `fullstack` モードに切り替わります。無ければアプリはクライアントのみ
7
+ (SPA)で、`/api/*` は単なるクライアントルートとして扱われます(本番と一致)。
8
+
9
+ ## API ルートの規約
10
+
11
+ API は `server/api/**` から、ページと同じファイル名規約で導出されます。
12
+
13
+ | ファイル | エンドポイント |
14
+ |---|---|
15
+ | `server/api/customers.ts` | `/api/customers` |
16
+ | `server/api/customers/[id].ts` | `/api/customers/:id` |
17
+ | `server/api/monthly-analysis.ts` | `/api/monthly-analysis` |
18
+
19
+ 各ファイルは HTTP メソッド名の関数をエクスポートします。使えるメソッドは
20
+ `GET` / `POST` / `PUT` / `PATCH` / `DELETE` / `OPTIONS`。
21
+
22
+ ```ts
23
+ // server/api/customers/[id].ts → /api/customers/:id
24
+ import type { ApiContext } from "@squadbase/vantage/server";
25
+ import { HttpError } from "@squadbase/vantage/server";
26
+
27
+ export async function GET({ params, env }: ApiContext) {
28
+ const customer = await findCustomer(params.id!);
29
+ if (!customer) throw new HttpError(404, "Customer not found");
30
+ return Response.json(customer);
31
+ }
32
+ ```
33
+
34
+ > [!NOTE]
35
+ > 有効な HTTP メソッドを 1 つもエクスポートしていない API ファイルは、`vantage check` が
36
+ > `INVALID_API_EXPORT` エラーで指摘します(小文字で書いた場合はヒントを出します)。
37
+
38
+ ## ApiContext
39
+
40
+ ハンドラは Web 標準の型で話します。引数の `ApiContext` は次を持ちます。
41
+
42
+ | プロパティ | 内容 |
43
+ |---|---|
44
+ | `request` | 標準の `Request` |
45
+ | `params` | 動的パラメータ(`params.id` など) |
46
+ | `env` | サーバー側の環境変数・シークレット |
47
+ | `waitUntil` | レスポンス後のバックグラウンド処理(撃ちっぱなし) |
48
+
49
+ 戻り値は標準の `Response`。`Response.json(...)` か、ヘルパーの `json()` を使えます。
50
+
51
+ ```ts
52
+ import { json } from "@squadbase/vantage/server";
53
+
54
+ export async function GET() {
55
+ return json({ ok: true });
56
+ }
57
+ ```
58
+
59
+ ## エラーの扱い
60
+
61
+ クライアントに見せたいエラーは `HttpError(status, message)` を throw します。これはステータスと
62
+ メッセージがそのままクライアントへ届きます。
63
+
64
+ ```ts
65
+ if (!authorized) throw new HttpError(403, "Forbidden");
66
+ ```
67
+
68
+ それ以外の throw されたエラーはサーバーにログされ、クライアントには**汎用の 500** として
69
+ 返されます(内部情報は漏れません)。
70
+
71
+ ## dev と prod は同一に振る舞う
72
+
73
+ リクエストのディスパッチ(ルートのマッチ・405 処理・request-id 付与)は dev と prod で
74
+ **共有された 1 つのコア**を通ります。開発時に見えた挙動が、本番でもそのまま再現されます。
75
+
76
+ ## シークレットはサーバーだけ
77
+
78
+ `ApiContext.env` はサーバー側でのみ読めます。**クライアントには決して届きません**。API キーや
79
+ DB 接続情報などはここから読みます。クライアントに露出させたい値の扱いは
80
+ [環境変数](environment-variables)を参照してください。
81
+
82
+ ## 次に読む
83
+
84
+ - [環境変数](environment-variables) — シークレットと公開値の境界
@@ -0,0 +1,279 @@
1
+ # ビルドとデプロイ
2
+
3
+ > dist/ の中身と vantage-manifest.json。同一オリジン配信と、フロント/サーバーを別オリジンに分けるデプロイ(S3+CloudFront ⇄ Lambda など)。
4
+
5
+ `vantage build` は本番用の成果物を `dist/` に出力します。ここから先の配信方法は 2 つに大別できます。
6
+ サーバーとフロントを**同一オリジン**でまとめて出すか、フロントを静的ホスティング(S3+CloudFront /
7
+ Cloudflare Pages)に、サーバーを別オリジン(Lambda / コンテナ)に**分けて**出すかです。分離構成の
8
+ ために Vantage は「API ベースURLの切り替え」と「CORS」を用意しています。
9
+
10
+ ## ビルド出力
11
+
12
+ ```bash
13
+ vantage build # → dist/
14
+ ```
15
+
16
+ ```text
17
+ dist/
18
+ ├── client/ クライアント(index.html + ハッシュ付きアセット、ルートごとに分割)
19
+ ├── server/index.mjs server/ がある場合のみ(esbuild / node20 / ESM バンドル)
20
+ └── vantage-manifest.json デプロイ契約
21
+ ```
22
+
23
+ `vantage-manifest.json` が配信側との唯一の契約です。フィールドは次の通り。
24
+
25
+ | フィールド | 内容 |
26
+ |---|---|
27
+ | `schemaVersion` | マニフェストのスキーマ版(現在 `1`) |
28
+ | `mode` | `"spa"`(client のみ)/ `"fullstack"`(server あり)。`server/` の有無から導出 |
29
+ | `client` | クライアント成果物への相対パス(`"./client"`) |
30
+ | `server` | サーバーバンドルへの相対パス(`"./server/index.mjs"`)。fullstack のみ |
31
+ | `spaFallback` | SPA フォールバック用 HTML(`"./client/index.html"`) |
32
+ | `runtime` | サーバーの実行環境(`"node"`) |
33
+
34
+ > [!NOTE]
35
+ > `mode` は `server/` ディレクトリの有無で自動的に決まります。`server/` が無ければ `spa`(クライアント
36
+ > のみ)、あれば `fullstack`。`vantage check` や `vantage routes` でも同じ判定が使われます。
37
+
38
+ ## preview でローカル確認
39
+
40
+ デプロイ前に、本番ビルドをローカルで動かして確認します。
41
+
42
+ ```bash
43
+ vantage preview
44
+ ```
45
+
46
+ `vantage preview` は `vantage-manifest.json` の `mode` を読み、`fullstack` なら Node サーバーを
47
+ 起動(既定 `:4173`)、`spa` なら静的プレビューを立ち上げます。
48
+
49
+ ## デプロイの 2 つの形
50
+
51
+ ### 同一オリジンにまとめる
52
+
53
+ Node プロセス 1 つで client と `/api` の両方を配信。設定が最小で、CORS も不要。
54
+
55
+ ### フロントとサーバーを分ける
56
+
57
+ フロントを S3+CloudFront 等へ、サーバーを Lambda / コンテナへ。API ベースURLの切り替えと
58
+ CORS が必要。
59
+
60
+ ## 同一オリジンにまとめてデプロイ
61
+
62
+ 最も単純な形です。`dist/` をまるごと Node が動く環境(コンテナ / VM)に置き、生成された
63
+ サーバーを起動します。同一プロセスが静的アセットと `/api/*` の両方を捌くため、API ベースURLの
64
+ 切り替えも CORS も不要です。
65
+
66
+ ```bash
67
+ # dist/ を配置したサーバー上で
68
+ PORT=8080 node dist/server/index.mjs
69
+ ```
70
+
71
+ サーバーはポート `PORT`(未指定なら `3000`)で待ち受けます。クライアントは相対パス
72
+ `/api/...` をそのまま同一オリジンで呼びます。
73
+
74
+ > [!NOTE]
75
+ > `spa` モード(`server/` なし)には起動するサーバーがありません。`dist/client/` を任意の静的
76
+ > ホスティングに置き、未知パスを `index.html` にフォールバックさせれば完了です(下の SPA
77
+ > フォールバック設定を参照)。
78
+
79
+ ## フロントとサーバーを分ける(S3+CloudFront ⇄ Lambda)
80
+
81
+ フロントを CDN の静的ホスティングに、サーバーを別オリジンに置く構成です。よくある組み合わせは
82
+ 「`dist/client` を S3+CloudFront、`dist/server/index.mjs` を Lambda / コンテナ」です。別オリジンに
83
+ なるため、次の 2 点が必要になります。
84
+
85
+ ### 1. API ベースURLを切り替える
86
+
87
+ クライアントの API 呼び出しは、`@squadbase/vantage/query` の `apiFetch` / `apiUrl` を通します。
88
+ これが `/api` を呼ぶ唯一の継ぎ目で、ベースURLをここで差し替えられます。
89
+
90
+ ```tsx
91
+ import { apiFetch, useQuery } from "@squadbase/vantage/query";
92
+
93
+ useQuery({
94
+ queryKey: ["monthly-analysis"],
95
+ // パスは server/api の綴りのまま(/api を含める)
96
+ queryFn: () => apiFetch("/api/monthly-analysis").then((r) => r.json()),
97
+ });
98
+ ```
99
+
100
+ ベースURLは `PUBLIC_API_BASE_URL` から読みます。**未設定なら空**で、従来どおり同一オリジンの
101
+ 相対パス(`/api/monthly-analysis`)になります。設定すると、その値が前置されます
102
+ (`https://api.example.com/api/monthly-analysis`)。切り替え方法は 2 つ。
103
+
104
+ **(a) 環境変数で上書き** — `.env` や CI の環境変数に置きます。`PUBLIC_` 接頭辞なので、
105
+ そのままクライアントバンドルに焼き込まれます。
106
+
107
+ ```bash
108
+ # .env(またはCIの環境変数)
109
+ PUBLIC_API_BASE_URL=https://api.example.com
110
+ ```
111
+
112
+ **(b) ビルド時にフラグで指定** — `vantage build` に `--api-base-url` を渡します。
113
+
114
+ ```bash
115
+ vantage build --api-base-url https://api.example.com
116
+ ```
117
+
118
+ > [!NOTE]
119
+ > `--api-base-url` は `.env` の `PUBLIC_API_BASE_URL` より**優先**されます。CI で基本値を `.env` に
120
+ > 置きつつ、環境ごとにフラグで上書きする、といった使い分けができます。
121
+
122
+ > [!TIP]
123
+ > `apiUrl("/api/...")` に渡すパスは、`server/api/**` の綴りのまま **`/api` を含めて**ください。
124
+ > ベースURLは「オリジン(またはその手前まで)」を表し、パスがそのまま連結されます。
125
+
126
+ ### 2. CORS を許可する
127
+
128
+ フロントとサーバーが別オリジンになると、ブラウザは CORS を要求します。サーバー側で
129
+ `CORS_ORIGIN` を設定すると、`/api` に CORS(プリフライトの `OPTIONS` 応答を含む)が付きます。
130
+ **未設定なら CORS は無効**で、同一オリジン運用はそのままです。
131
+
132
+ ```bash
133
+ # サーバー(Lambda / コンテナ)の環境変数
134
+ CORS_ORIGIN=https://app.example.com # 単一オリジン
135
+ # CORS_ORIGIN=https://a.example.com,https://b.example.com # カンマ区切りで複数
136
+ # CORS_ORIGIN=* # すべて許可(credentials とは併用不可)
137
+ CORS_CREDENTIALS=true # Cookie / 認証情報を許可する場合のみ
138
+ ```
139
+
140
+ | 変数 | 役割 |
141
+ |---|---|
142
+ | `CORS_ORIGIN` | 許可するオリジン。`*` / 単一 / カンマ区切りの複数。未設定なら CORS 無効 |
143
+ | `CORS_CREDENTIALS` | `true` のとき資格情報(Cookie 等)を許可。`*` とは併用しない |
144
+
145
+ 許可メソッドは Vantage の API が使える `GET,POST,PUT,PATCH,DELETE,OPTIONS` が自動で設定されます。
146
+ この挙動は dev サーバーと本番 Node サーバーで**共通**なので、開発中に CORS を確認できます。
147
+
148
+ ### 3. フロントを静的ホスティングに置く
149
+
150
+ `dist/client/` を S3(+ CloudFront)や Cloudflare Pages にアップロードします。SPA なので、
151
+ 未知パスは `spaFallback`(`index.html`)に返す必要があります。
152
+
153
+ - **S3 + CloudFront**: CloudFront の「カスタムエラーレスポンス」で `403` / `404` を
154
+ `/index.html`(ステータス `200`)に書き換えます。
155
+ - **S3 静的ウェブサイトホスティング**: エラードキュメントを `index.html` にします。
156
+ - **Cloudflare Pages**: SPA フォールバックが既定で有効です。
157
+
158
+ ### 4. サーバーを Lambda / コンテナに置く
159
+
160
+ `dist/server/index.mjs` は `PORT` で待ち受ける Node の HTTP サーバーです(マニフェストの
161
+ `runtime` は `"node"`)。Node プロセスが動く環境にそのまま置けます。
162
+
163
+ - **コンテナ(Cloud Run / ECS·Fargate / Render / Fly など)**: `node dist/server/index.mjs` を
164
+ 起動コマンドにし、`PORT` を渡します。
165
+ - **AWS Lambda**: 待ち受け型の Node サーバーなので、コンテナイメージ + AWS Lambda Web Adapter
166
+ など「HTTP サーバーをそのまま Lambda で動かす」方式が相性の良い選択です。
167
+ - シークレット(DB 接続情報や API キー)は**サーバー側の環境変数**として渡します。これらは
168
+ `ApiContext.env` からのみ読め、クライアントには決して届きません。
169
+
170
+ > [!WARNING]
171
+ > 本番の Node サーバーは**起動時に一度だけ** `process.env` をスナップショットします(dev はリクエスト
172
+ > ごとに読み直します)。デプロイ後に環境変数を変えたら、サーバーを再起動してください。
173
+
174
+ ## AWS Lambda へデプロイする(具体例)
175
+
176
+ 生成される `dist/server/index.mjs` は `PORT` で**待ち受ける** Node の HTTP サーバーです。一方
177
+ Lambda は「イベントでハンドラを呼ぶ」モデルなので、待ち受け型のサーバーをそのまま動かすには
178
+ [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter)(LWA)を挟むのが
179
+ 素直です。LWA が Function URL / API Gateway のイベントを、ローカルで動く HTTP サーバーへ
180
+ プロキシします。Vantage 側のコード変更は不要です。
181
+
182
+ ### 1. コンテナイメージで動かす(推奨)
183
+
184
+ esbuild が `dist/server/index.mjs` に**単一ファイルとしてバンドル**するため、`node_modules` を
185
+ 持ち込む必要はありません。
186
+
187
+ ```dockerfile
188
+ # Dockerfile
189
+ FROM public.ecr.aws/docker/library/node:20-slim
190
+
191
+ # Lambda Web Adapter を拡張として同梱(バージョンは適宜更新)
192
+ COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
193
+
194
+ WORKDIR /var/task
195
+ # dist/ ごとコピー(server は ../client を参照するためレイアウトを保つ)
196
+ COPY dist ./dist
197
+
198
+ # LWA と Node サーバーの待受ポートを一致させる(LWA の既定は 8080)
199
+ ENV PORT=8080
200
+ CMD ["node", "dist/server/index.mjs"]
201
+ ```
202
+
203
+ ```bash
204
+ vantage build # dist/ を生成
205
+ docker build -t vantage-api .
206
+
207
+ # ECR にログインして push(<acct> / <region> は自分の値に)
208
+ aws ecr get-login-password --region ap-northeast-1 \
209
+ | docker login --username AWS --password-stdin <acct>.dkr.ecr.ap-northeast-1.amazonaws.com
210
+ docker tag vantage-api <acct>.dkr.ecr.ap-northeast-1.amazonaws.com/vantage-api:latest
211
+ docker push <acct>.dkr.ecr.ap-northeast-1.amazonaws.com/vantage-api:latest
212
+ ```
213
+
214
+ この image で Lambda 関数を作成し、**Function URL** を有効にすると HTTPS エンドポイントが
215
+ 得られます。これを CloudFront の `/api/*` オリジンにするか、フロントの `PUBLIC_API_BASE_URL` に
216
+ 直接指定します。
217
+
218
+ > [!TIP]
219
+ > **zip で動かす場合**
220
+ > コンテナを使わず zip でも動かせます。バンドル済みなので `dist/server/index.mjs`(必要なら
221
+ > `dist/client` も)を zip し、LWA を **Lambda レイヤー**として付与、環境変数
222
+ > `AWS_LAMBDA_EXEC_WRAPPER=/opt/bootstrap` と `PORT=8080` を設定、ランタイムは Node.js 20.x に
223
+ > します。
224
+
225
+ ### 2. Lambda の環境変数を設定する
226
+
227
+ サーバー設定とシークレットは Lambda の環境変数として渡します(クライアントには届きません)。
228
+
229
+ | 変数 | 例 | 用途 |
230
+ |---|---|---|
231
+ | `CORS_ORIGIN` | `https://d111111abcdef8.cloudfront.net` | フロントのオリジンを許可 |
232
+ | `CORS_CREDENTIALS` | `true` | Cookie / 認証情報を使う場合のみ |
233
+ | `SECRET_*` など | `sk_live_xxx` | `ApiContext.env` から読むシークレット |
234
+
235
+ `PORT` は Dockerfile で設定済みです(LWA の既定 8080 に合わせています)。
236
+
237
+ > [!NOTE]
238
+ > Function URL 自体にも CORS 設定がありますが、アプリ側(`CORS_ORIGIN`)と**二重に設定すると
239
+ > 競合**します。Vantage の `CORS_ORIGIN` に一本化し、Function URL 側の CORS は空にしておくのが
240
+ > 分かりやすい構成です。
241
+
242
+ ### 3. フロントから Lambda を指す
243
+
244
+ フロントのビルド時に、Lambda(または前段の CloudFront)のオリジンを `PUBLIC_API_BASE_URL` に
245
+ 指定します。
246
+
247
+ ```bash
248
+ vantage build --api-base-url https://d111111abcdef8.cloudfront.net
249
+ ```
250
+
251
+ `apiUrl("/api/monthly-analysis")` はこのオリジンに `/api/monthly-analysis` を連結して呼びます。
252
+
253
+ > [!WARNING]
254
+ > Lambda はコールドスタート時にプロセスを起動し、そのとき `process.env` を読み込みます。環境変数を
255
+ > 変更したら、新しいバージョンをデプロイして反映させてください(実行中の環境には遡って効きません)。
256
+
257
+ ## 本番の環境変数のまとめ
258
+
259
+ 境界は接頭辞で決まります([環境変数](environment-variables)も参照)。
260
+
261
+ | 種類 | どこで設定 | いつ効く | 例 |
262
+ |---|---|---|---|
263
+ | クライアント公開値 | ビルド時(`.env` / `--api-base-url`) | ビルドに焼き込み | `PUBLIC_API_BASE_URL` |
264
+ | サーバー設定 | サーバーの環境変数 | 起動時に読む | `PORT`, `CORS_ORIGIN`, `CORS_CREDENTIALS` |
265
+ | シークレット | サーバーの環境変数 | 起動時に読む(`ApiContext.env`) | `SECRET_API_KEY` など |
266
+
267
+ ## デプロイ前チェックリスト
268
+
269
+ - [ ] `vantage check` がエラーなしで通る
270
+ - [ ] `vantage build`(分離構成なら `--api-base-url` 付き、または `.env` に `PUBLIC_API_BASE_URL`)
271
+ - [ ] `vantage preview` でローカル動作を確認
272
+ - [ ] 分離構成なら、サーバー側に `CORS_ORIGIN`(フロントのオリジン)を設定
273
+ - [ ] 静的ホスティング側で SPA フォールバック(未知パス → `index.html`)を設定
274
+ - [ ] シークレットはサーバーの環境変数にのみ置く(クライアントに出さない)
275
+
276
+ ## 次に読む
277
+
278
+ - [CLI リファレンス](cli-reference) — `build` のフラグを含む全コマンド
279
+ - [環境変数](environment-variables) — 公開値とシークレットの境界