このドキュメントは Supabase(DB) と Vercel(ホスティング・環境変数) と Gemini(AI・サーバー専用キー) をつなぐための最短手順です。順番どおりに進めてください。
---
GEMINI_PAID_PLAN_CONFIRMED 参照)---
| やり方 | 手順 |
|--------|------|
| Git が Vercel と連携済み | 本番用ブランチ(多くは main)へ push するだけ。ダッシュボードでビルドが走り、完了すると本番 URL が更新されます。 |
| この PC から CLI で出す | リポジトリ直下で npm install のあと npm run deploy。先に npx vercel login 済みで、フォルダが Vercel プロジェクトと リンク(初回は vercel link か vercel deploy の対話)されている必要があります。 |
| プレビュー URL だけ欲しい | npm run deploy:preview(本番ドメインではなくプレビュー用 URL が付きます)。 |
環境変数を変えた直後は、Save したうえで Redeploy または上記 npm run deploy まで行うとビルドに新しい値が載ります。
---
SUPABASE_SERVICE_ROLE_KEY)の差し替え場所一覧Supabase でキーをローテーションしたあと、次の 該当する行だけ 新しい値に直します(ソースコードや .env.example には実キーを書きません)。
| 場所 | どこを開くか | 設定する名前 | 備考 |
|------|----------------|--------------|------|
| ① このPC(ローカル) | リポジトリ直下の .env.local を編集 | SUPABASE_SERVICE_ROLE_KEY | .gitignore 対象。右辺を新キーに差し替え。 |
| ② このPC(ローカル) | 同上 .env.local | SUPABASE_URL | api/mental-health*.js 用。VITE_ なし。Project URL と同じでよい。 |
| ③ 本番・プレビュー(Vercel) | [Vercel](https://vercel.com) → プロジェクト → Settings → Environment Variables | SUPABASE_SERVICE_ROLE_KEY | Value 列を新キーに上書き。Production / Preview など使っている環境すべて。 |
| ④ Vercel | 同上 | SUPABASE_URL | VITE_ なしの URL。メンタルヘルス API 用に設定している場合のみ更新。 |
| ⑤ 一時的(CLI) | PowerShell 等でコマンド実行時のみ | SUPABASE_SERVICE_ROLE_KEY | 例: $env:SUPABASE_SERVICE_ROLE_KEY="…"(.env.local を読まない実行向け) |
家族通知・ディスパッチ API(notify-family / family-notification-dispatch)も SUPABASE_SERVICE_ROLE_KEY と SUPABASE_URL(または VITE_SUPABASE_URL) を参照します。キーは上表と同じ変数名で統一してください。
書き換えないもの
.env.example … あくまで雛形(実キー禁止)src/・api/ 内のソース … キーは埋め込まない(process.env で読むだけ)差し替え後の作業
vercel dev を再起動---
1. [Supabase Dashboard](https://supabase.com/dashboard) で New project を作成します。
2. データベースのパスワードを控えます(後で直接はほぼ不要ですが、バックアップ用に保存推奨)。
---
1. Supabase ダッシュボードで対象プロジェクトを開きます。
2. 左メニュー SQL Editor を開きます。
3. New query を選び、リポジトリ内の次のファイルの 全文 をコピーして貼り付けます。
supabase/migrations/20260419120000_init.sql
4. Run を実行します。エラーがなければテーブル・RLS・ストレージバケット・デモ施設データが作成されます。
init.sql のあと、Git の supabase/migrations/ にある 時系列の番号付き SQL を、未適用のものから順に SQL Editor で実行するか、supabase db push で適用します。
| ファイル(例) | 概要 |
|----------------|------|
| 20260424_220000_face_auth.sql | 顔認証・face_logs 等 |
| 20260424_mental_health.sql | メンタルヘルス |
| 20260426120000_tenant_features.sql | テナント機能フラグ |
| 20260429120000_med_image_ai_staff_log.sql | AI 画像分析ログ |
| 20260429140000_consent_audit_ai.sql | 同意・監査 |
| 20260503120000_image_change_detection.sql | 画像変化検知テーブル・RLS |
| 20260505120000_get_previous_image_record_rpc.sql | 前回画像取得 RPC |
| 20260510120000_family_notification_optimization.sql | 家族通知ログ family_notification_logs・RLS・索引(閲覧パターン最適化の遅延通知) |
試験用ダミーデータはマイグレーションに含めません。必要なときだけ SQL Editor で [scripts/sql/dummy-image-change-test-data.sql](../scripts/sql/dummy-image-change-test-data.sql) を実行します(手順・削除・テスト段階は [dummy-data-creation-guide.md](./dummy-data-creation-guide.md))。家族通知の SQL 参照用全文は [docs/sql/family_notification_optimization.sql](./sql/family_notification_optimization.sql) も併せてください。
tenants / residents / profiles などが見えることrecord-photos バケットがあることimage_change_detections / image_analysis_log が存在し、Database → Functions に get_previous_image_record があることfamily_notification_logs テーブルと関連 RLS が存在すること---
1. Project Settings(歯車)→ API を開きます。
2. 次をコピーします(Vercel に貼るため)。
https://xxxx.supabase.co 形式 sb_publishable_…)または Legacy の anon public(eyJ... の JWT)> Secret(sb_secret_…)と service_role(JWT)はフロントや Git に入れないでください。ブラウザからは Publishable または anon のみ使用します。
> 補足: api/mental-health.js / api/mental-health-batch.js や CLI が シークレット / service_role を参照する場合は、Vercel(または vercel dev)に SUPABASE_URL と SUPABASE_SERVICE_ROLE_KEY(Legacy JWT またはダッシュボードの Secret と同列のサーバー用キー)を VITE_ なしで設定します。キーをローテーションしたら 差し替え、再デプロイしてください。
---
1. 左メニュー Authentication → Providers を開きます。
2. Email プロバイダを有効にします(メール確認の要否は運用に合わせて設定)。
---
1. [Vercel Dashboard](https://vercel.com) でこのプロジェクトを開きます。
2. Settings → Environment Variables を開きます。
3. 少なくとも次の 必須 3 項目 を追加し、必要に応じて 任意 2 項目 を追加します(名前は 完全一致 で)。
| Name | Value | 適用先 |
|------|--------|--------|
| VITE_SUPABASE_URL | Supabase の Project URL | Production, Preview, Development すべて推奨 |
| VITE_SUPABASE_ANON_KEY | Publishable(sb_publishable_…)または Legacy の anon public(JWT) | 同上。sb_secret_ や service_role JWT を入れない(ブラウザで Forbidden になる) |
| GEMINI_API_KEY | Google の Gemini API キー | 同上(サーバー専用。VITE_ は付けない) |
| GEMINI_PAID_PLAN_CONFIRMED | true または 1 | Gemini を使う場合は必須(無料プラン運用禁止のサーバー側ガード) |
| SUPABASE_URL(任意) | Project URL(VITE_ なし) | メンタルヘルス API / バッチ・画像変化検知 API・家族通知 API 等で service_role を使う場合 |
| SUPABASE_SERVICE_ROLE_KEY(任意) | service_role シークレット | 上記を使う場合のみ。画像変化検知では RPC・署名付き URL 解決に使用。notify-family / family-notification-dispatch にも必要。キー更新後は差し替え→再デプロイ |
| CRON_SECRET(推奨) | ランダムな長い文字列 | Vercel Cron が呼ぶ /api/mental-health-batch・/api/precursor-alerts-batch・/api/family-notification-dispatch の不正利用防止。Authorization: Bearer(値は環境変数と同一) |
4. Save 後、再デプロイが必要です。
> VITE_ で始まる変数だけがブラウザに埋め込まれます。GEMINI_API_KEY・SUPABASE_SERVICE_ROLE_KEY は api/ やサーバーからのみ参照され、クライアントには出ません。
vercel.json で次がスケジュールされます(UTC)。
| パス | 時刻(UTC) | 内容 |
|------|----------------|------|
| /api/mental-health-batch | 0 21 * * * | 利用者ごとに記録を集約し、Gemini(/api/mental-health)でリスク参考情報を更新 |
| /api/precursor-alerts-batch | 15 21 * * * | daily_records 過去90日からルール検知し、team_messages に「予兆アラート」(Gemini 不使用) |
| /api/family-notification-dispatch | 30 21 * * * | family_notification_logs の予定時刻到来分を処理し contact_messages へ挿入(Gemini 不使用)。Vercel Hobby では 1 日 1 回までの Cron しか持てないため、当初案の 10 分毎は Pro プランまたは外部 Cron に切り替えるまで日次運用 |
CRON_SECRET を設定している場合、Cron の Authorization と一致させる(本番では設定推奨)。feature-precursor-alerts.md](./feature-precursor-alerts.md) · 家族通知: [feature-family-notification.md](./feature-family-notification.md)画像変化検知を本番で使う場合(追加メモ)
/api/save-staff-action は、サーバー上で VITE_SUPABASE_ANON_KEY と職員の Bearer access_token を組み合わせ、RLS のまま image_change_detections を更新します。Vercel に VITE_SUPABASE_ANON_KEY が無いと 503 になります。/api/* を呼ぶため、ローカル検証は npm run dev だけでは足りないことがあります。npx vercel dev**(または npm run dev:vercel)またはデプロイ済み URL で試してください。feature-image-change-detection.md](./feature-image-change-detection.md) · 試験手順: [dummy-data-creation-guide.md](./dummy-data-creation-guide.md)---
1. [Google AI Studio](https://aistudio.google.com/) などで API キーを作成します。
2. そのキーを Vercel の GEMINI_API_KEY に設定します(上記)。
モデル名は既定で gemini-2.0-flash です。利用プランやリージョンで失敗する場合は、api/gemini.js の既定モデル文字列を gemini-1.5-flash などに変更するか、将来クライアントから model を渡す実装に拡張できます。
---
デプロイ済み URL(本番例: https://tsunagarucho.jp)で確認します。
1. ホームが開く
2. ログイン画面で Supabase にユーザーを作成したうえでログインできる(Auth 設定後)
3. 職員記録で記録を保存でき、Supabase の Table Editor → daily_records に行が増える
4. Gemini で申し送り案 を押すと、申し送り欄に文章が入る(GEMINI_API_KEY 設定済み・本番または vercel dev)
5. (任意)職員記録で写真付き保存後、同一利用者に前回画像付き記録がある場合、画像変化検知の API・パネルが動く(SUPABASE_SERVICE_ROLE_KEY・関連マイグレ済み・Storage に実画像)
6. (任意)予兆アラート:Cron 実行後、team_messages に [予兆アラート] が増えるか(閾値を満たすテストデータがある場合)
7. (任意)家族通知:記録保存から family_notification_logs が増え、family-notification-dispatch 実行後に contact_messages が増えるか([feature-family-notification.md](./feature-family-notification.md))
8. ログイン画面の言語切替:https://(本番)/login.html で地球アイコンから英語等へ切替え、文言が変わること([feature-login-i18n.md](./feature-login-i18n.md))
npm run dev だけでは /api/gemini が無いことがあります。
npx vercel dev
---
| 現象 | 対処 |
|------|------|
| ログイン時に Forbidden use of secret API key in browser と出る | VITE_SUPABASE_ANON_KEY を Publishable または Legacy anon(JWT) に直す。sb_secret_(シークレット) と service_role(JWT) は SUPABASE_SERVICE_ROLE_KEY(VITE_ なし)にだけ。Vercel の Production / Preview 両方を確認し、再デプロイ。 |
| ログインできない | Email プロバイダ有効化・メール確認設定・RLS まわりを確認 |
| 記録が保存されない | VITE_SUPABASE_* がデプロイに反映されているか再デプロイ |
| Gemini が 503 | Vercel に GEMINI_API_KEY が無い、または再デプロイ前 |
| Gemini が 502 | モデル名や API キー権限、Google 側の利用制限を確認 |
| 画像変化検知が 503 / 失敗 | Vercel に SUPABASE_SERVICE_ROLE_KEY と SUPABASE_URL(または VITE_SUPABASE_URL)、VITE_SUPABASE_ANON_KEY が揃っているか。npm run dev 単体では /api が無い → vercel dev または本番 URL で試す |
| OpenCV が読み込めない | CDN(docs.opencv.org)への到達・端末のメモリ。回線制限でブロックされていないか |
| メンタル/予兆の Cron が 401 | CRON_SECRET を Vercel に入れた場合、Cron の Bearer と一致しているか確認 |
| 予兆アラートが飛ばない | 過去90日・閾値・同一コード 36時間以内の重複抑止 を確認。daily_records に食事・気分・体重が入っているか |
| vercel deploy が Cron で失敗(Hobby limit 等) | vercel.json の crons[].schedule が 1 日 1 回以下か確認。短間隔が必要なら Pro または 外部スケジューラで /api/... を叩く |
| ログインで言語を変えても日本語のまま | public/locales の login キーと login.html の data-i18n、login.js の i18n:locale 再適用を確認([feature-login-i18n.md](./feature-login-i18n.md)) |
| 家族通知が飛ばない | マイグレ適用・SUPABASE_SERVICE_ROLE_KEY・職員 JWT 経由の notify-family・Cron の CRON_SECRET・日次ディスパッチの待ち時間を確認 |
---
家族ロールでサインアップしたユーザーは、profiles.resident_id を デモ利用者の UUID などに手動で設定する必要がある場合があります。Supabase SQL Editor で更新するか、Table Editor で profiles を編集します(運用ルールに合わせてください)。
---
実企業・契約施設で運用するときは、次を揃えると安全です。
| 項目 | 内容 |
|------|------|
| public/config/tenants.v1.json | テナントID(tenants.slug と一致)ごとに brand_name・public_notice_ja・ai_disclaimer_ja を定義。デプロイ後は /config/tenants.v1.json で配信されます。 |
| QR | 本番 URL が決まったら qr-tenant.html(ルート直下)で ?tenant= 付きURLのQRを発行。 |
| 手順書 | docs/operator-onboarding-ja.html(運営者)· docs/facility-playbook-ja.html(現場)· docs/terms-enterprise-ja.html(利用上の注意のひな形)。 |
| 索引 | [DOCUMENTATION_INDEX.md](./DOCUMENTATION_INDEX.md) … 仕様・手順・public/docs の法務資料への対応表 |
HTTP セキュリティヘッダは vercel.json で設定しています。
以上です。