📚 システム構造書

リラクゼーションサロン向け・問い合わせ管理 Web アプリ(2 ブランド対応

悟空のきもち(ドライヘッドスパ・goku-nokimochi.com)GOKU SPA(ボディトリートメント・gokuspa.jp)の 2 ブランドのお問い合わせメール / フォーム / 電話メモを一元管理し、外注スタッフへの権限分離と AI 返信案を実現する社内向け業務アプリ

📅 作成日: 2026年5月24日
🏗️ 構築フェーズ: Phase 3 後半(Pattern B 実装中)
💰 月額コスト目安: 約 1,700〜3,350円(heteml 2 契約・要確認)
👥 想定ユーザー: 3〜5名(社内+外注)
🏪 ブランド: 悟空のきもち / GOKU SPA
📌 一言で言うと
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 で送信 ▼ お客様 選んだアドレスから届いたように見える
🟢
DNS リスクゼロ
MX を触らない
🟢
Gmail も継続
既存転送はそのまま
🟢
障害時の保険
heteml + Gmail で業務継続可能
🟢
即ロールバック
転送設定1行削除で復旧

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 に分散保存
⚠️
退職時リスク
個人 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(ギフト券の問い合わせ) ← 別チケット ・どちらも「田中花子様」の顧客カードに紐づく

フォールバック対応(隠しヘッダーが壊れていたら)

🎯
第1優先
In-Reply-To で一致
📚
第2優先
References チェーンで一致
📝
第3優先
件名「Re:」+ メアド一致
🆕
該当なし
新規チケット作成
💡 一言で
メール標準の「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 # UI 最終デザイン(v3) ├── wrangler.toml # Cloudflare 設定 ├── package.json │ ├── db/ │ ├── schema.sql # 11 テーブル定義 │ └── seed.sql # モックデータ初期投入 │ ├── functions/ # Cloudflare Pages Functions(API) │ ├── _lib/ │ │ └── db.ts # D1 共通ヘルパー │ └── api/ │ ├── tickets/ │ │ ├── index.ts # GET /api/tickets │ │ ├── [id].ts # GET /api/tickets/:id │ │ └── [id]/ │ │ ├── status.ts # PATCH .../status │ │ └── assign.ts # PATCH .../assign │ └── customers/ │ └── [email].ts # GET / PUT /api/customers/:email │ ├── public/ # 静的ファイル + 公開フロント │ ├── index.html # トップ │ ├── contact.html # お問い合わせフォーム(既存) │ │ │ └── admin/ # 管理アプリ本体 │ ├── index.html # 受信トレイ │ ├── ticket.html # チケット詳細 │ ├── compose.html # 新規送信 │ ├── notifications.html # 通知センター │ ├── preview.html # PC+SP プレビュー │ │ │ ├── css/ │ │ ├── app.css # 共通スタイル(Gmail 風) │ │ ├── ticket.css # 詳細ページ用 │ │ ├── compose.css # 新規送信用 │ │ └── notifications.css # 通知用 │ │ │ └── js/ │ ├── api.js # API クライアント(D1 連携) │ ├── mock-data.js # API 失敗時のフォールバック │ ├── app.js # 共通ヘルパー │ ├── customer.js # CustomerStore + TicketStore │ ├── 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