中級編のカリキュラムへ

中級編35

中級② お問い合わせフォームとメール通知をつける

フォーム→保存→メール通知。Webサービスの定番パターンを一周する

“使われるサービス”には、使った人の声が届く窓口が要ります。今日はお問い合わせフォームを作ります。流れは「フォームに入力→データベースに保存→あなたにメールで通知」。このフォーム→保存→通知は、予約・応募・注文…あらゆるWebサービスの土台になる定番パターンです。

今日のゴール

スマホから問い合わせを送ると、あなたのメールボックスに通知が届くこと。前半(保存)と後半(通知)の2段構えで、1段ずつ動かします。

STEP1:保管棚とRLS——今回は“ポスト”を作る

SupabaseのSQL Editorで実行します。今回のRLSは初級⑤と違う形なのがポイント。お問い合わせはログインしていない人も送れる必要があるから「投函はだれでもOK」、でも中身を読めるのは管理者(あなた)だけだから「開封のルールは作らない」——つまりポストです。

create table if not exists public.contacts (
  id bigint generated always as identity primary key,
  name text not null check (char_length(name) <= 100),
  email text not null check (char_length(email) <= 200),
  body text not null check (char_length(body) <= 2000),
  created_at timestamptz not null default now()
);

alter table public.contacts enable row level security;

drop policy if exists "contacts_insert_anyone" on public.contacts;
create policy "contacts_insert_anyone"
  on public.contacts for insert
  to anon, authenticated
  with check (true);

RLSの考え方が一歩深まった

select(読む)のポリシーをあえて作らないので、アプリ経由ではだれも読めません。あなたはSupabaseのダッシュボード(Table Editor)で読みます。RLSは「全部禁止が基本。必要な操作だけ、必要な相手に開ける」——この感覚が身につくと、設計が一気に安全になります。

STEP2:フォームを実装してもらう

/contact ページにお問い合わせフォームを作って。項目は名前・メールアドレス・本文。送信したらサーバー側で public.contacts テーブルに保存して、「送信しました」の画面を出す。空欄や長すぎる入力はエラーメッセージを表示。ヘッダーにContactへのリンクも追加して。まず計画を見せて。
  1. 計画OK→実行→mainに反映。
  2. 公開URLの /contact からテスト送信。
  3. SupabaseのTable Editorで contacts を開き、届いていることを確認——前半クリア!

STEP3:メール送信サービス(Resend)に登録

メールはVercelからは直接送れないので、メール送信の専門サービスを使います。おすすめは Resend(リセンド)——開発者向けの定番で、個人の通知用途なら無料枠で十分です。

  1. resend.com でサインアップ(GitHubでOK——もう慣れたものですね)。
  2. 「API Keys」→「Create API Key」でキーを発行し、メモ帳にコピー(一度しか表示されません)。
  3. テスト送信は、Resendが用意している差出人 onboarding@resend.dev から「自分の登録メール宛て」に送れます(独自ドメインを持っていれば、あとで差出人にできます)。

STEP4:キーを環境変数へ——NEXT_PUBLICを付けない!

Vercelの「Settings → Environment Variables」で、名前 RESEND_API_KEY、値にさっきのキーを追加→Redeploy。ここで超重要な注意があります。

NEXT_PUBLIC_ を付けるかどうかの分かれ目

NEXT_PUBLIC_ で始まる環境変数は“ブラウザに公開してよい値”という意味で、誰でも見られます。SupabaseのanonキーはRLSで守られている前提の公開用だからOKでした。でもResendのAPIキーは、漏れたら他人があなたの名義でメールを送り放題になる“秘密の鍵”。だから NEXT_PUBLIC_ を付けず、サーバー側だけで使う。この区別ができれば、もう環境変数は卒業です。

STEP5:通知を実装してもらう

お問い合わせが保存できたら、Resend で通知メールを送るようにして。resend パッケージを使い、環境変数 RESEND_API_KEY はサーバー側のコードだけで使う(ブラウザに出さない)。差出人は onboarding@resend.dev、宛先は私のメールアドレス(あとで教える値を環境変数 CONTACT_TO に入れる)。件名は「新しいお問い合わせ:名前」、本文に名前・メール・内容を入れて。メール送信に失敗しても、保存自体は成功扱いにして。まず計画を見せて。

環境変数 CONTACT_TO(あなたのメールアドレス)もVercelに追加してRedeploy。それから /contact でもう一度テスト送信——メールボックスに通知が届いたら完成です!

おさらい:今日使った“言葉”

フォーム→保存→通知
Webサービスの定番パターン。予約も応募も注文も、骨格はこれ。
ポスト型のRLS
insertだけ開けて、selectは閉じる。投函はだれでも、開封は管理者だけ。
Resend
メール送信の専門サービス。アプリからのメールは専門サービス経由が常識。
NEXT_PUBLIC_の有無
付ける=ブラウザに公開してよい値。付けない=サーバー専用の秘密。

中級②・完成チェック

0 / 4

つまずいたら

①保存はされるがメールが来ない→Vercelのログ(Functions)のエラーをコピーしてAIへ。迷惑メールフォルダも確認。②環境変数を足したのに動かない→Redeployしたか確認(鉄板の見落とし)。③フォームから「権限エラー」→insertポリシーのSQLを実行し忘れていないか確認。

お疲れさまでした!

ユーザーの声が届く窓口ができました。次回③はいよいよあなたのアプリにAIを組み込みます。Claude APIを自分のサービスから呼ぶ——作る側として一番ワクワクする回です。