📚 システム構造書
リラクゼーションサロン向け・問い合わせ管理 Web アプリ(2 ブランド対応)
悟空のきもち(ドライヘッドスパ・goku-nokimochi.com)と GOKU SPA(ボディトリートメント・gokuspa.jp)の 2 ブランドのお問い合わせメール / フォーム / 電話メモを一元管理し、外注スタッフへの権限分離と AI 返信案を実現する社内向け業務アプリ
📌 一言で言うと
Gmail のような見た目で、2 ブランド(悟空のきもち / GOKU SPA)のサロン業務に特化した問い合わせ管理ツール。
方針:両ドメインとも heteml は継続(MX 変更なし)し、heteml の転送機能で Cloudflare にも届ける Pattern B 構成。
DNS 切替リスクをゼロにしつつ、本システムで 2 ブランドのメールを一元管理・AI 仕訳・Resend 送信を実現する。
受信メールは to_address のドメインで brand を自動判定し、UI でブランドフィルタ可能。
個人 Gmail への既存転送は保険として並行運用継続。
🔧 メール基盤の方針:Pattern B(2 ドメイン構成)
MX レコードは 両ドメインとも heteml のまま維持。heteml の転送機能で Cloudflare にも届ける、リスクゼロの並行運用構成。
受信時の to_address ドメインで brand(gnk / spa)を自動判定。
受信ルート(2 ブランド共通の流れ)
【悟空のきもち】
お客様 ──メール送信──▶ info@/reserve@/order@goku-nokimochi.com
│
▼
heteml(MX:変更なし)
│
┌───────────┴───────────┐
▼ 既存転送 ▼ 新規追加転送
個人 Gmail inbox@mail.goku-nokimochi.com
(保険として継続) │
▼
Cloudflare Email Routing
│
▼
Email Worker
・to_address ドメインで brand 判定
・ヘッダー解析(Message-ID 等)
・スレッディング判定 / AI 自動仕訳
│
▼
D1 データベース(tickets.brand='gnk')
│
▼
本システム(受信トレイ)
【GOKU SPA】
お客様 ──メール送信──▶ info@gokuspa.jp
│
▼
heteml(別契約・MX:変更なし)
│
┌───────────┴───────────┐
▼ 既存転送 ▼ 新規追加転送
個人 Gmail inbox@mail.gokuspa.jp
│
▼
Cloudflare Email Routing
│
▼
Email Worker(共通)
│
▼
D1 データベース(tickets.brand='spa')
送信ルート
本システム(返信エディタ)
│ チケットの brand に応じた送信元を選択
│ gnk → info@/reserve@/order@goku-nokimochi.com
│ spa → info@gokuspa.jp
▼
POST /api/messages/send
│
▼
Resend API
│ goku-nokimochi.com / gokuspa.jp 両方の SPF/DKIM で送信
▼
お客様
選んだアドレスから届いたように見える
🟢
障害時の保険
heteml + Gmail で業務継続可能
4 つのドメイン構成(2 ブランド分)
| ブランド |
ドメイン |
MX 向き先 |
役割 |
悟空のきもち (gnk) |
goku-nokimochi.com |
heteml(変更なし) |
お客様向けの正面玄関(info@/reserve@/order@) |
mail.goku-nokimochi.com |
Cloudflare(新規) |
本システムの裏口受信箱(inbox@) |
goku-nokimochi.com の TXT |
— |
SPF/DKIM/DMARC で Resend からの送信を許可 |
GOKU SPA (spa) |
gokuspa.jp |
heteml(別契約・変更なし) |
お客様向けの正面玄関(info@) |
mail.gokuspa.jp |
Cloudflare(新規) |
本システムの裏口受信箱(inbox@) |
gokuspa.jp の TXT |
— |
SPF/DKIM/DMARC で Resend からの送信を許可(別 DKIM 鍵) |
👥 業務体制(2 ブランド共通の 3 階層エスカレーション)
お問い合わせが届くと、内容に応じて自動で①または②へ振り分け。
判断に迷う・重要案件は人間が手動で③上司にエスカレ。
悟空のきもち / GOKU SPA の 2 ブランド共通のフロー。スタッフは基本ブランド別だが、両方対応できる人もいる。顧客はクロス利用あり(同一メアドで両店利用)。
① 外注の人(メイン担当)
全ての問い合わせをまず受け取る。
一般・健康相談・物販・回数券など 8割を対応。
判断に迷ったら ③ にエスカレ。
② 予約担当(社内)
予約変更・キャンセル・新規予約など、
時間調整が必要な案件のみ。
自動振り分けキーワードで判定。
↓ ①②で判断不可な場合(手動エスカレ)
③ 上司(社内・最終判断)
妊娠中の施術可否・クレーム・返金・特例対応など、
経営判断が必要な案件。
①または②が「📤 担当を変更」から手動エスカレ。
🏗️ 技術スタック(Pattern B 構成)
heteml(既存)を残しつつ、Cloudflare + Resend で本システムを構築。低コスト・低リスク・段階移行可能。
🎨 フロントエンド
Pure HTML / CSS / JS
Gmail 風 UI
レスポンシブ(PC + SP)
PWA 対応予定
🔌 バックエンド
Cloudflare Pages Functions
TypeScript
REST API
🗄️ データベース
Cloudflare D1(SQLite)
11+ テーブル
メアド主キー
📥 メール受信(Pattern B)
heteml(MX 維持・継続)
heteml 転送機能
Cloudflare Email Routing
(mail. サブドメイン)
📤 メール送信
Resend API
SPF / DKIM / DMARC
送信元プルダウン
🤖 AI(切替可能)
OpenAI(GPT-4o / mini)
Gemini(Pro / Flash)🌟
Claude(Sonnet / Haiku)
環境変数で切替
🔐 認証
Cloudflare Access
Google Workspace SSO
パスワードレス
🌊 データの流れ
お客様からの問い合わせが受信され、スタッフが返信するまでの流れ。
📥 受信フロー(Pattern B)
お客様 ──メール──▶ heteml(MX:変更なし)
│ 既存転送
├──▶ 個人 Gmail(保険として継続)
│
│ 新規追加転送
└──▶ inbox@mail.goku-nokimochi.com
│
▼
Cloudflare Email Routing
│
▼
Email Worker
・ヘッダー解析(Message-ID 等)
・スレッディング判定(3段)
・キーワード分類 + AI 仕訳
│
▼
D1 データベース
tickets / messages / customers / senders
│
▼
受信トレイ画面
(リアルタイム表示)
📤 返信フロー
受信トレイ ──クリック──▶ チケット詳細画面
│
├─ 「✨ AI 返信案」 ──▶ Claude API ──返信案──┐
│ │
├─ 「📋 テンプレ挿入」 ──▶ D1 templates │
│ │
└─◀──────────────────────────────────────────────────┘
│
返信文を編集
│
▼
/api/messages/send
│
▼
Resend API ──送信──▶ お客様
│
▼
tickets.status = 'sent'
送信済みBOXへ自動移動
🔄 既存運用との接続(業務フロー移行)
現状の「3つの heteml メアド → 各スタッフ Gmail」運用から、本システムへの一元集約へ段階的に移行する計画。
Pattern B(heteml 継続 + 並行運用)を採用し、DNS リスクをゼロに。heteml と保険用 Gmail を残しつつ、本システムをメインに移行する。
現状の業務フロー(Before)
① お問い合わせフォーム経由
お客様 ──フォーム入力──▶ noreply@ ──▶ info@(heteml)
│ 転送設定
▼
各スタッフ Gmail ── Gmail で確認
│
▼
スタッフが reserve@(heteml) から返信
│
▼
お客様
│ 返信
▼
reserve@(heteml)
│ 転送設定
▼
各スタッフ Gmail ── Gmail で確認・返信
② 電話代行経由
お客様 ──電話──▶ 電話代行サービス
│ メール送信
├──▶ order@(heteml)
│ │ 転送設定
│ ▼
│ 各スタッフ Gmail
│
└──▶ 担当スタッフの個人メアドにも直接
スタッフが内容確認 → 電話で対応 or reserve@ からメール返信
現状の課題
📨
メアド分散
3 メアド + 全 Gmail に重複
⚠️
退職時リスク
個人 Gmail にデータ残る
💸
heteml 月額
プラスプラン 約 2,200円/月
🔁
noreply の不便
お客様が直接返信できない
After(Pattern B):heteml 経由で本システムに集約
[ 全てのお客様接点 ]
📝 フォーム送信 💬 お客様返信 📞 電話代行
(info@) (reserve@) (order@)
│ │ │
└──────────┬──────┴──────────────────┘
↓
heteml(MX:変更なし・継続)
│
┌──────────┴──────────┐
▼ 既存転送 ▼ 新規追加転送
個人 Gmail inbox@mail.goku-nokimochi.com
(保険として継続) │
▼
Cloudflare Email Routing
│
▼
Email Worker
│
▼
D1 データベース
│
▼
本システム(メイン)
│
▼
全メール・電話代行を一元管理
├─ 顧客プロファイル(メアドキー)
├─ チケット化・ステータス管理
├─ AI 返信案生成
├─ メモ・履歴蓄積(永続)
└─ 通知(PWA / アプリ内 / Slack)
│
▼
スタッフが本システムから対応
├─ 返信は reserve@/info@/order@ から選択して送信(Resend)
└─ 履歴は1箇所に完全蓄積
チャネル別の自動処理
どのメアドに届いたかで、自動的に違う処理が走る。
📝 フォーム経由(info@)
チャネル: form
新規チケットとして登録 → キーワード判定で自動振り分け → AI フラグ検知
noreply@ は不要(reply-to を info@ に設定するだけ)
💬 お客様返信(reserve@)
チャネル: email
In-Reply-To ヘッダーで既存スレッド検索 → 同じチケットに統合
見つからなければ新規チケット作成
📞 電話代行(order@)
チャネル: phone_proxy
電話代行サービスからの定型メールを解析 → お客様名・電話番号・用件を抽出
チケット化して「電話代行」マーキング → 折り返し対応可
送信側:送信元の使い分け
| シーン |
送信元 |
理由 |
| 既存問い合わせへの返信 |
reserve@ |
既存運用と同じ・お客様も馴染みあり |
| 電話代行案件のメールフォロー |
reserve@ |
返信系統一 |
| 新規お知らせ・キャンペーン |
info@ |
「お知らせ用」と分かる |
| 予約確認の自動送信 |
reserve@ |
予約系統一 |
→ 本システムのドロップダウンで 1 クリック切替(送信元アドレス選択機能・後述)
5 段階の移行プラン(Pattern B・リスクゼロ)
Pattern B は heteml を残し続ける前提の構成。Step 5 の MX 切替・heteml 解約は 任意の将来オプションであり、必須ではない。
Step 1
本システム稼働開始(Pattern B-α〜δ)
mail. サブドメインの MX を Cloudflare に
SPF/DKIM/DMARC を Resend 用に追加
Email Worker / Resend / AI を実装
※ goku-nokimochi.com の MX は触らない
Step 2
並行運用開始(Pattern B-ε / 〜1ヶ月)
heteml で info@/reserve@/order@ に
「inbox@mail.」転送先を追加
個人 Gmail への転送は維持(保険)
本システムで返信を試す
Step 3
返信は本システム化(1〜2ヶ月)
スタッフは本システムから返信
Gmail での個別返信は禁止
Gmail は閲覧のみ(バックアップ)
システムが履歴を蓄積
Step 4
個人 Gmail を保険用1つに集約(継続)
各スタッフの Gmail 転送は順次 OFF
1つだけ「監視用 Gmail」を残す
例:boss@golden-field.jp
通常は見ない・月1チェック
Step 5(任意)
MX 切替検討(半年〜1年後 or 永久に保留)
本システムが完全に安定したら検討
MX を Cloudflare に切替 → heteml 解約
月 1,650円 を削減できる
※ heteml を保険として継続する選択も合理的
スタッフの 1 日の流れ:Before / After
Before(Gmail 時代)
朝 → Gmail を開く → info@/reserve@/order@ 転送が全部届く
→ 同じメールが他スタッフにも届いてる
→ 「これ自分の担当?」と判別
→ Gmail で返信(reserve@ になりすまし)
→ お客様返信は Gmail に来る
→ 履歴は個人 Gmail に散在
After(本システム時代)
朝 → 本システムを開く(PC または スマホ PWA)
→ 受信トレイ:未対応リストが一覧表示
→ チャネル別アイコンで「フォーム / メール / 電話代行」が即判別
→ ⭐ 要対応マーク・🟠 返信あり・🔵 上司確認中 を絞り込み
→ クリックして詳細表示・AI 返信案で下書き生成
→ 送信ボタン → 自動的に送信済みボックスへ
→ 全履歴は1箇所に永続保存
noreply@ の扱い(廃止)
Before:
フォーム → noreply@ から info@ に送信
→ お客様には noreply@ が送信元として表示
→ お客様が返信しようとしても届かない
After:
フォーム → info@ に直接保存(noreply@ は使わない)
→ お客様への自動返信も reply-to: info@ で設定
→ お客様が「返信」を押すと info@ に届く
→ 本システムが受信して既存スレッドに自動紐付け
→ お客様体験が「普通にメール会話できる」に改善
💡 一言で(Pattern B 方針)
heteml は残す。MX も触らない。
heteml の転送機能で本システムにもメールを届ける = リスクゼロで一元管理を実現。
個人 Gmail への転送も継続(保険)。本システムを「メイン」、Gmail を「サブ」として運用。
heteml 解約・MX 切替は将来の任意オプションであり、永久に保険として残す選択も合理的。
📨 送信元アドレス選択の仕組み
「サロン受付 / 京都店 / 銀座店 / 予約担当」など、1つのアプリから複数のメアドで送り分けできる仕組み。
お客様には、選んだアドレスからの送信に見える。
カギは「ドメイン認証は1回だけ」
ドメインごとに認証すれば、配下のアドレスは全部使える
DNS(ドメイン設定)に1回だけ登録:
・SPF レコード ──▶ "Resend からの送信を許可"
・DKIM レコード ──▶ 電子署名の公開鍵
・DMARC レコード ──▶ なりすまし対策ポリシー
⬇️ これだけで…
✅ info@yourdomain.com
✅ kyoto@yourdomain.com
✅ ginza@yourdomain.com
✅ reserve@yourdomain.com
✅ ...いくつでも追加可能(追加認証 不要)
3 つのレイヤー構成
① DNS(一度だけ)
ドメイン管理者が DNS レコードを追加。
Resend ダッシュボードで認証ステータスが「✅ Verified」になれば完了。
以後、このドメインのどのアドレスでも送信可能に。
② D1 データベース
senders テーブルに登録:
・brand(gnk / spa)
・email(info@goku-nokimochi.com 等)
・display_name(悟空のきもち / GOKU SPA など)
・signature(自動付与する署名)
③ アプリ
画面でドロップダウンから選択。
API が選ばれた sender_id を見て、Resend に送信。
From フィールドが「選んだアドレス」になる。
具体的な送信フロー
スタッフが 返信エディタ でドロップダウンから「悟空のきもち お問い合わせ窓口」を選ぶ
│ (チケットの brand='gnk' に応じて選択肢が絞り込まれる)
▼
sender_id = 'snd-gnk-info'
│
▼
POST /api/messages/send
│
▼
D1 から「snd-gnk-info」の情報を取得
・brand: gnk
・email: info@goku-nokimochi.com
・display_name: 悟空のきもち お問い合わせ窓口
│
▼
Resend API
From: "悟空のきもち お問い合わせ窓口 <info@goku-nokimochi.com>"
│
▼
お客様
「悟空のきもち お問い合わせ窓口」から
メールが届いて見える
※ GOKU SPA の場合は brand='spa' で sender_id='snd-spa-info'
From: "GOKU SPA お問い合わせ窓口 <info@gokuspa.jp>"
権限制御も可能(誰がどれを使えるか)
user_senders テーブルでスタッフごとに使える送信元を制限できる。
🤝 外注 Aさん(悟空のきもち専属)
└─ info@goku-nokimochi.com のみ使用可
→ ドロップダウンには gnk の info だけ表示
💼 予約担当(悟空のきもち・社内)
└─ reserve@goku-nokimochi.com / info@goku-nokimochi.com を使用可
→ ドロップダウンに gnk の 2 つ表示
🌿 GOKU SPA 担当(社内)
└─ info@gokuspa.jp のみ使用可
→ ドロップダウンに spa の 1 つ表示
👑 上司(両ブランド)
└─ 全アドレス使用可
→ ドロップダウンに 4 アドレス全表示(gnk: 3 + spa: 1)
→ ブランド・店舗・役割をまたいだ「なりすまし」ができないセキュア設計
💡 一言で
DNS で「ドメイン全体」を認証 → アプリで「個別アドレス」を切替。
Gmail の「他のアドレスから送信」と同じ仕組みを、管理画面で集約した形。
🔗 スレッド統合の仕組み(返信を同じ会話に紐付ける)
お客様が返信したメールを、「これは前回の○○の続き」と自動判別して同じチケットに統合する仕組み。
お客様が件名から「Re:」を消してもバラけない、メール標準の堅牢な方法を採用。
カギは「メールの隠しヘッダー」
すべてのメールには 3 つの隠しヘッダーが付いている:
📬 Message-ID
そのメール固有の ID(指紋)
例: <abc123@yourdomain.com>
🔗 In-Reply-To
「私はこのメールへの返信です」と示す ID
例: <abc123@yourdomain.com>
📚 References
会話の全履歴(Message-ID の連鎖)
例: <m1@...> <m2@...> <m3@...>
→ メールアプリ(Gmail/Outlook 等)が
返信時に自動でこれを設定してくれる
具体例:田中花子様との3往復
1通目(お客様からの新規問い合わせ)
Message-ID: <msg-001@gmail.com>
In-Reply-To: (なし)
件名: 妊娠中の施術可否について
⬇️ 受信 Worker が処理
⬇️ 新規チケット作成(T-2026-0234)
⬇️ messages テーブルに保存
2通目(スタッフからの返信)
Message-ID: <msg-002@yourdomain.com>
In-Reply-To: <msg-001@gmail.com> ← 1通目を参照
件名: Re: 妊娠中の施術可否について
⬇️ アプリから送信時に
⬇️ 自動でこのヘッダーを付ける
⬇️ messages テーブルに保存(同じ ticket_id)
3通目(お客様からの再返信)
Message-ID: <msg-003@gmail.com>
In-Reply-To: <msg-002@yourdomain.com> ← 2通目を参照
件名: ありがとうございます
⬇️ 受信 Worker が処理
⬇️ 「In-Reply-To = msg-002」で DB 検索
⬇️ 既存メッセージ発見 → 同じチケットに追加
⬇️ ステータスを「返信あり」に更新
受信時の判定フロー
お客様 ──返信──▶ Cloudflare Email Routing
│
▼
受信 Worker 起動
│
┌────────────────────┴────────────────────┐
▼ ▼
① In-Reply-To ヘッダー取得 ② Message-ID で DB を検索
SELECT ticket_id FROM messages
WHERE message_id = ?
│
┌────────────────────┴────────────────────┐
▼ ▼
✅ 見つかった ❌ 見つからない
↓ ↓
同じチケットに 新しい顧客の新規問い合わせ
メッセージを追加 → 新規チケットを作成
ステータスを → デフォルトステータス
「返信あり」に変更 「未返信」で登録
同じお客様の別件はどうなる?
田中花子様が、別件で新しく問い合わせ
Message-ID: <new-msg@gmail.com>
In-Reply-To: (なし・新規メール)
件名: 別件:ギフト券について
⬇️ In-Reply-To がない = 完全新規
⬇️ でもメアドは hanako@example.com
⬇️ → 顧客は「田中花子様」として認識
⬇️ → 新規チケットを作成(既存とは別物)
⬇️ → 顧客プロファイル(メモ・過去履歴)は共有
結果:
・チケット A(妊娠中の問い合わせ)
・チケット B(ギフト券の問い合わせ) ← 別チケット
・どちらも「田中花子様」の顧客カードに紐づく
フォールバック対応(隠しヘッダーが壊れていたら)
📚
第2優先
References チェーンで一致
💡 一言で
メール標準の「In-Reply-To」ヘッダーで会話を追跡する仕組み。
Gmail/Outlook も同じ方法で「スレッド表示」している。
お客様が件名を変えても、Re: を消しても、隠しヘッダーで繋がる。
📱 画面構成(6 画面)
スタッフが日常的に使う画面の一覧。すべて PC + SP 対応。
📥
受信トレイ
/admin/
問い合わせ一覧。Gmail 風単一行表示。フィルタ・検索・スター可。
📧
チケット詳細
/admin/ticket.html?id=...
スレッド型表示。返信エディタ・AI 返信案・メモ・担当変更。
✉️
新規送信
/admin/compose.html
こちらから送信。1名宛て / 予約配信。テンプレ・AI 文案。
🔔
通知センター
/admin/notifications.html
通知一覧・設定。要注意・アサイン・返信・メンション。
📤
送信済みBOX
/admin/?filter=sent
送信完了したチケット。お客様返信があれば「返信あり」で戻る。
👁
プレビュー
/admin/preview.html
開発時の PC + SP 同時確認用ページ。
🏷️ チケットステータス(5種類)
問い合わせライフサイクルを表現する5つの状態。スタッフ操作で自動遷移。
遷移ルール
🔴 未返信 ──[スター⭐]────▶ 🟡 要対応
🔴 未返信 ──[送信]────────▶ 🟢 送信済み(送信済みBOXへ移動)
🔴 未返信 ──[上司に確認]──▶ 🔵 上司確認中
🟢 送信済み ──[顧客から再返信]▶ 🟠 返信あり(受信トレイへ復帰)
🟠 返信あり ──[クリックで開く]▶ 🔴 未返信(自動解除)
🤖 AI 機能(コスト最適化設計)
キーワードルール(無料)で 9 割対応 + AI で残りを補完する設計。
AI プロバイダーは OpenAI / Gemini / Claude から選択可能。環境変数で切替できる柔軟設計。
機能別の AI 利用箇所
🎯 自動仕訳(無料・即時)
「予約変更」「キャンセル」等のキーワードで①外注 / ②予約担当に自動振り分け。AI を使わずルールベース。
無料
🚨 AIフラグ自動検知
「妊娠」「アレルギー」「持病」「クレーム」等のキーワードを検出し、要注意フラグを自動付与。
無料
✨ AI返信案生成
スタッフが「✨ AI で生成」ボタンを押した時のみ、選択した AI プロバイダーで返信案を生成。
プロバイダー次第
📋 テンプレ展開
顧客名などの変数を自動置換。AI は使わずシンプルな文字列置換。
無料
🔌 プロバイダー比較(月50回利用時のコスト試算)
1回あたり入力 1,000 トークン / 出力 500 トークン と仮定(日本語の典型的な返信案サイズ)。
| プロバイダー |
モデル |
月コスト(50回) |
品質 |
特徴 |
| OpenAI |
GPT-4o-mini |
約 3円 |
⭐⭐⭐⭐ |
最安・最速・コスパ最強 |
| Gemini |
2.5 Flash |
約 12円 |
⭐⭐⭐⭐ |
Google Workspace 親和性◎ |
| Claude |
Haiku 3.5 |
約 21円 |
⭐⭐⭐⭐ |
丁寧な日本語 |
| Gemini |
2.5 Pro |
約 47円 |
⭐⭐⭐⭐⭐ |
上位モデル・Workspace 統合 |
| OpenAI |
GPT-4o |
約 56円 |
⭐⭐⭐⭐⭐ |
万能・最速・汎用性◎ |
| Claude |
Sonnet 4.5 |
約 80円 |
⭐⭐⭐⭐⭐ |
敬語・共感的文章が秀逸 |
※ 50回/月ならどのモデルでも月100円以下。プロバイダーの違いはコストよりも、品質・速度・既存ツール親和性で選ぶレベル。
🔄 プロバイダー切替の仕組み
// functions/_lib/ai.ts
export async function generateReply(prompt, env) {
const provider = env.AI_PROVIDER || 'openai'; // 環境変数で切替
switch (provider) {
case 'openai': return callOpenAI(prompt, env); // GPT-4o-mini
case 'gemini': return callGemini(prompt, env); // Gemini Flash
case 'claude': return callClaude(prompt, env); // Sonnet 4.5
}
}
// 環境変数 AI_PROVIDER を変えるだけで、コード変更なしに切替可
用途別の使い分け(推奨)
⚡ 軽量・大量処理
AI 自動分類・要約など、大量に呼ばれる処理。
→ GPT-4o-mini / Gemini Flash
コスト:1回あたり 0.05〜0.25円
✨ 高品質・返信案
お客様への返信文生成。品質重視。
→ GPT-4o / Gemini 2.5 Pro / Claude Sonnet 4.5
コスト:1回あたり 1〜2円
🎯 特殊用途
感情分析・長文要約など、高度な判断。
→ 上位モデルを必要な時だけ呼ぶ
ハイブリッド構成も可
💡 一言で
3社(OpenAI / Gemini / Claude)どれも使える設計。
環境変数 1 つで切替可能。50回/月の利用なら、どれを選んでも月100円以下。
御社が既に持っている API キー、または Google Workspace の親和性で選べばOK。
🗄️ データベース構造(11 テーブル・2 ブランド対応)
Cloudflare D1(SQLite)で構築。メアドを主キーに顧客とチケットを永続的に紐付けるのが特徴。
2 ブランド対応のため、senders / tickets / customers / templates / salon_knowledge の 5 テーブルに brand 列('gnk' | 'spa' | 'common')を追加済み。
users
スタッフ(3役割)
PK: email
customers
お客様情報・メモ(クロス利用あり)
PK: email + brand 列
tickets
問い合わせ案件(brand で振り分け)
PK: id, FK: customer_email + brand 列
messages
送受信・内部メモ
PK: id, FK: ticket_id
senders
送信元アドレス(gnk:3 / spa:1)
PK: id + brand 列
templates
返信テンプレート(brand 別 + common)
PK: id + brand 列
salon_knowledge
サロン情報・FAQ(brand 別 + common)
PK: id + brand 列
notifications
アプリ内通知
PK: id
activities
監査ログ(変更履歴)
PK: id, 追記のみ
push_subscriptions
PWA プッシュ通知
PK: id
ai_usage_log
AI コスト追跡
PK: id
settings
システム設定(KV)
PK: key
📂 ファイル構成
主要ディレクトリのみ抜粋。実際は node_modules/ 等も存在。
メーリアプリ/
├── README.md
├── 要件定義書.md
├── システム構造書.html
├── 画面設計_推奨版.html
├── wrangler.toml
├── package.json
│
├── db/
│ ├── schema.sql
│ └── seed.sql
│
├── functions/
│ ├── _lib/
│ │ └── db.ts
│ └── api/
│ ├── tickets/
│ │ ├── index.ts
│ │ ├── [id].ts
│ │ └── [id]/
│ │ ├── status.ts
│ │ └── assign.ts
│ └── customers/
│ └── [email].ts
│
├── public/
│ ├── index.html
│ ├── contact.html
│ │
│ └── admin/
│ ├── index.html
│ ├── ticket.html
│ ├── compose.html
│ ├── notifications.html
│ ├── preview.html
│ │
│ ├── css/
│ │ ├── app.css
│ │ ├── ticket.css
│ │ ├── compose.css
│ │ └── notifications.css
│ │
│ └── js/
│ ├── api.js
│ ├── mock-data.js
│ ├── app.js
│ ├── customer.js
│ ├── inbox.js
│ ├── ticket.js
│ ├── compose.js
│ ├── notifications.js
│ └── notification-bell.js
│
└── docs/
└── superpowers/
└── plans/
├── 2026-05-24-phase-2-implementation.md
└── 2026-05-24-phase-3-backend.md
🎯 構築進捗
4 フェーズ構成。Phase 1〜3 部分まで完了。
✅ 完了
Phase 1: 基本 UI
受信トレイ画面
Gmail 風レイアウト
絞り込み・検索
レスポンシブ対応
✅ 完了
Phase 2: 全機能 UI
チケット詳細(メールスレッド)
AI 返信案(モック)
顧客メモ(メアド主キー)
新規送信・通知センター
ステータス再設計(5種)
受信トレイ / 送信済みBOX 分離
🔄 進行中
Phase 3: バックエンド (Pattern B)
✅ 前半: D1 接続・API・フロント連携
⏳ α: Resend / DNS / heteml 転送 準備
⏳ β: AI 抽象化・送信機能
⏳ γ: 受信 Worker・スレッディング
⏳ δ: AI 仕訳・返信案
⏳ ε: 統合テスト・並行運用開始
⏳ 予定
Phase 4: 本番化
Cloudflare Access 認証
Google Workspace SSO
PWA 化(プッシュ通知)
セキュリティ監査
本番デプロイ
💰 運用コスト試算(Pattern B・2 ブランド・月100件処理時)
heteml 継続を前提とした構成。Cloudflare の無料枠を最大活用。AI も最小限の利用に抑える設計。
⚠️ heteml の月額は契約形態により変動:2 ドメインが 1 契約に収まるか別契約かは要確認。下表は「別契約 = 2 倍」のケースを示す(最も保守的な見積)。
| サービス |
用途 |
標準運用 |
想定外伸び時 |
| heteml プラスプラン × 2 ドメイン |
既存メール受信・両ドメインの MX 維持(要確認) |
1,650〜3,300円 |
1,650〜3,300円 |
| Cloudflare Pages |
静的ホスティング |
0円 |
0円 |
| Cloudflare Workers / D1 |
API・データベース |
0円 |
750円 |
| Cloudflare Email Routing |
mail.goku-nokimochi.com / mail.gokuspa.jp の 2 サブドメインで受信 |
0円 |
0円 |
| Cloudflare Access |
認証(〜50ユーザー) |
0円 |
0円 |
| Resend |
メール送信(2 ドメイン認証・〜3,000通合算) |
0円 |
0円 |
| AI API(OpenAI / Gemini / Claude のいずれか) |
AI 返信案(月50〜500回) |
50円 |
500円 |
| 合計(月) |
約 1,700〜3,350円 |
約 2,900〜4,550円 |
| 合計(年) |
約 20,400〜40,200円 |
約 34,800〜54,600円 |
※ heteml は両ドメインとも既存契約として継続(既に支払い中)。本システム導入の追加コストは 月 +50〜+1,250円。
※ heteml の契約形態(1 契約で 2 ドメイン or 別契約で 2 倍)は実際の請求書を確認のこと。
※ 比較:formrun(既製品 SaaS)= 3,980円〜 / Re:lation = 17,800円〜
※ 将来的に MX 切替→heteml 解約に進めば、両ドメイン分の heteml 月額を削減可能。
Created with Claude Code · リラクゼーションサロン問い合わせ管理システム · v1.0