「誰のための、何をしてもらうサイトか」を 1 文にします。例:小さなデザイン事務所が、見積もりの問い合わせをもらうためのサイト。
問い合わせフォーム・LINE 連携付きの企業サイトを作る
5 ページの企業サイトに問い合わせフォームを付け、送信をメールと LINE 公式アカウントへ通知する。トークンはコードに書かない。
この教材で作るもの
トップ・サービス・会社情報・お問い合わせ・プライバシーポリシーの 5 ページ。問い合わせフォームを送ると、管理者のメールと LINE 公式アカウントに 1 通ずつ通知が届く。Vercel で公開済み。
動作確認環境: Node.js 20 / Next.js 15(App Router) / Vercel(2026年10月時点の無料枠) / LINE Messaging API(push message) / Resend(メール送信)
前提条件
- GitHub アカウント
- Vercel アカウント(無料枠でよい)
- LINE Developers のプロバイダーと Messaging API チャネル(無料)
- Resend のアカウント(無料枠でよい。別のメール送信サービスでも可)
- Node.js 20 以上と、Claude Code か Cursor
実装手順
-
作りたいものを 1 文で決める
確認: 1 文で言えたら次へ
-
AI に情報設計を出してもらう
1 文をプロンプトに入れて、5 ページの見出し構成とフォーム項目を出してもらいます。分からない点は推測させず、質問として返してもらいます。
AI に渡すプロンプト要件を 1 文から情報設計にするclaude-code
あなたは Web 制作者です。次の 1 文から、企業サイトの情報設計を提案してください。 作りたいもの: <ここに 1 文。例: 小さなデザイン事務所の、問い合わせをもらうためのサイト> 出力: - 5 ページ(トップ / サービス / 会社情報 / お問い合わせ / プライバシーポリシー)それぞれの目的と見出し構成 - トップに載せる要素の優先順位 - 問い合わせフォームの項目(必須 / 任意) - まだ決まっていないことの質問リスト(推測で埋めない)
確認: 5 ページの見出しとフォーム項目が決まった
-
プロジェクトを作って GitHub に置く
npx create-next-app@latestでプロジェクトを作り、最初のコミットを GitHub に置きます。手順は AI で 0 から Web サービスを公開する の STEP 4〜15 と同じです。確認: GitHub にリポジトリができた
-
静的サイトの骨子を作る
5 ページと共通ヘッダー・フッターを作ってもらいます。文章はあとで差し替えるので、まずは構造と見た目だけを整えます。
AI に渡すプロンプト静的サイトの骨子を作るclaude-code
Next.js(App Router)で 5 ページの静的な企業サイトを作ってください。 条件: - ページ: / , /services , /company , /contact , /privacy - 共通ヘッダー(ロゴ・ナビ)と共通フッター(会社名・プライバシーポリシーへのリンク) - CSS はフレームワークを使わず、CSS Modules か素の CSS。色は --primary: #6e4bff を基調に - 画像はプレースホルダーでよい(alt は必ず付ける) - スマートフォン幅(375px)で崩れないこと - 各ページの title と description を設定すること 作ったら、起動コマンドと確認手順を最後に書いてください。
確認: 5 ページが表示され、375px で崩れない
-
問い合わせフォームと API ルートを作る
フォームと受け口の API を作ります。この段階では通知を送らず、受け付けた内容をサーバーのログに出すだけにして、検証とレート制限が効くことを先に確かめます。
AI に渡すプロンプト問い合わせフォームと API ルートclaude-code
/contact に問い合わせフォームを作り、送信先として API ルート app/api/contact/route.ts を作ってください。 フォーム: - 項目: お名前(必須)、メールアドレス(必須・形式チェック)、お問い合わせ内容(必須・最大 2000 文字) - ハニーポット用の非表示項目(入力があれば受け付けない) - 送信中はボタンを無効化し、成功 / 失敗をテキストで表示(aria-live="polite") API: - POST のみ。JSON を受け取り、サーバー側でも同じ検証を行う - 同じ IP から 1 分に 3 回を超えたら 429 を返す(メモリ上の簡易制限でよい) - 成功したら { ok: true } を返す。通知の送信は次のステップで実装するので、いまは console.log で内容を出すだけにする - 秘密情報は一切ハードコードしないコード例app/api/contact/rate-limit.ts
const hits = new Map<string, number[]>(); export function tooMany(ip: string, limit = 3, windowMs = 60_000) { const now = Date.now(); const recent = (hits.get(ip) ?? []).filter((t) => now - t < windowMs); recent.push(now); hits.set(ip, recent); return recent.length > limit; }確認: 空送信が拒否され、連打すると 429 になる
-
LINE Developers でチャネルを用意する
LINE Developers コンソールでプロバイダーと Messaging API チャネルを作り、チャネルアクセストークン(長期)を発行します。通知先は自分のユーザー ID(チャネル基本設定の「あなたのユーザー ID」)です。公式アカウントを友だち追加しておきます。
トークンは
.envに書きます。.env.exampleにはキー名とプレースホルダーだけを書きます。コード例.env.example
# 実際の値は .env(git には入れない)と Vercel の環境変数にだけ置く RESEND_API_KEY=<ここに貼る:Resend の API キー> CONTACT_TO=<ここに貼る:通知を受け取るメールアドレス> CONTACT_FROM=<ここに貼る:Resend で認証した差出人> LINE_CHANNEL_ACCESS_TOKEN=<ここに貼る:LINE Developers のチャネルアクセストークン> LINE_TO=<ここに貼る:通知先の LINE ユーザー ID>確認: .env にトークンがあり、.env.example には実際の値が無い
-
メールと LINE に通知する
API ルートに通知処理を足します。環境変数が無いときは落ちずにスキップし、片方が失敗してももう片方は送るようにします。
AI に渡すプロンプトメールと LINE への通知claude-code
app/api/contact/route.ts に、受け付けた問い合わせを 2 か所へ通知する処理を追加してください。 1. メール: Resend の SDK で管理者宛に送る。API キーは環境変数 RESEND_API_KEY、宛先は CONTACT_TO、差出人は CONTACT_FROM 2. LINE: Messaging API の push message で、環境変数 LINE_CHANNEL_ACCESS_TOKEN と LINE_TO(通知先のユーザー ID)を使って送る。本文は「お名前 / メール / 内容の先頭 200 文字」 条件: - 環境変数は process.env から読み、未設定のときは 500 ではなく「設定が足りません」とログに出して { ok: false } を返す - トークンや宛先をコードや .env.example に実際の値で書かない。.env.example にはキー名とプレースホルダー(<ここに貼る:…>)だけを書く - 片方の送信が失敗しても、もう片方は送る - 個人情報をログに残さない(名前・メール・本文をそのまま console.log しない)コード例app/api/contact/line.ts
export async function notifyLine(text: string) { const token = process.env.LINE_CHANNEL_ACCESS_TOKEN; const to = process.env.LINE_TO; if (!token || !to) { console.warn('LINE notification skipped: environment is not configured'); return false; } const res = await fetch('https://api.line.me/v2/bot/message/push', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ to, messages: [{ type: 'text', text: text.slice(0, 1000) }] }), }); return res.ok; }確認: テスト送信でメールと LINE に 1 通ずつ届く
-
プライバシーポリシーに通知先を書く
問い合わせ内容を「メールと LINE で運営者に通知し、サーバーには保存しない」ことをプライバシーポリシーに明記します。文面は運営者が確認してから公開します。
確認: 通知先と保存しない旨が書かれている
-
公開前チェックを AI に出してもらう
秘密情報の混入、検証、レート制限、表示崩れを表で確認します。問題があればその場で直します。
AI に渡すプロンプト公開前のセルフチェックclaude-code
このプロジェクトを公開する前に、次を確認して結果を表にしてください。 - .env が .gitignore に入っていて、git ls-files .env が空 - .env.example に実際の値が入っていない - API ルートで入力を検証している(必須・長さ・メール形式・ハニーポット・レート制限) - 問い合わせ内容を永続化していない(通知だけ) - プライバシーポリシーに「問い合わせ内容をメールと LINE で運営者に通知する」ことが書いてある - 375px で全ページが崩れない - 各ページに title と description がある 問題があれば、修正案も一緒に出してください。
確認: 表のすべてが OK
-
Vercel に公開する
Vercel でリポジトリを取り込み、環境変数(5 つ)を Vercel 側に登録してからデプロイします。公開 URL でフォームを 1 回送信し、通知が届くことを確かめます。
確認: 公開 URL からの送信でメールと LINE に届く
テスト・検証
チェックはこのブラウザにだけ保存されます。
| 済 | 項目 | やり方 | 期待結果 |
|---|---|---|---|
| 公開 URL からテスト送信する | メールと LINE 公式アカウントに 1 通ずつ届き、本文に名前・メール・内容の先頭が含まれる | ||
| 必須項目を空にして送る。メール欄に abc と入れて送る | 送信されず、エラー文が表示される(画面と API の両方で拒否) | ||
| 1 分以内に 4 回送る | 4 回目は 429 になり、通知は 3 通まで | ||
| 開発者ツールで非表示項目に文字を入れて送る | 受け付けられず、通知も届かない | ||
| git ls-files .env を実行し、.env.example を開く | 何も表示されず、.env.example はプレースホルダーだけ | ||
| ローカルで .env を外して送信する | 500 にならず、ログに「設定が足りません」と出る | ||
| Vercel のログを見る | 名前・メール・本文がそのまま出ていない | ||
| 端末エミュレーションで 5 ページを見る | 横スクロールが出ず、フォームが押せる |
安全性・秘密情報
- チャネルアクセストークンとメール API キーは .env と Vercel の環境変数にだけ置く。コード・コミット・このページには書かない
- .env を .gitignore に入れ、公開前に git ls-files .env が空であることを確認する
- LINE API はブラウザから直接叩かず、必ずサーバー(API ルート)から送る
- 入力はサーバー側でも検証し、ハニーポットとレート制限で迷惑送信を減らす
- 問い合わせ内容はサーバーに保存せず通知だけにし、プライバシーポリシーに通知先を書く
- ログに個人情報(名前・メール・本文)をそのまま出さない
「<ここに貼る:…>」の形で書かれた値は、環境変数など公開されない場所に置きます。コード・リポジトリ・このページには入れません。
公開手順
- Vercel で GitHub リポジトリを取り込む
- Vercel の Environment Variables に .env.example の 5 項目を登録する(Production)
- デプロイ後、公開 URL から 1 回テスト送信して通知を確認する
- 独自ドメインを設定し、HTTPS になっていることを確認する
- Search Console にサイトを登録する
よくあるエラー
- 送信しても LINE に届かない
-
原因: LINE_TO が自分のユーザー ID ではない、または公式アカウントを友だち追加していない。トークンの期限切れや Vercel に環境変数を登録していないことも多い
対処: LINE Developers の「あなたのユーザー ID」を LINE_TO に入れ、公式アカウントを友だち追加する。Vercel の環境変数を確認して再デプロイする
- メールは届くのに LINE だけ失敗する(401)
-
原因: チャネルアクセストークンが間違っている、または別チャネルのもの
対処: LINE Developers で長期トークンを再発行し、.env と Vercel の両方を更新する
- ローカルでは届くのに公開後は届かない
-
原因: .env は git に入れていないので、Vercel 側に環境変数が無い
対処: Vercel の Environment Variables に 5 項目を登録して再デプロイする
- 正しい入力でも 429 になる
-
原因: レート制限の窓(1 分 3 回)にテスト送信が引っかかっている
対処: 1 分待つか、開発中だけ上限を上げる。本番の値は戻す
- GitHub にトークンを push してしまった
-
原因: .env をコミットした、またはコードに直書きした
対処: すぐに LINE Developers と Resend でトークンを無効化・再発行し、履歴から削除する。再発行しない限り漏れたトークンは使われ続ける
AIへの実装指示書
この教材の手順・プロンプト・検証・安全性を 1 枚にまとめた Markdown です。コピーして Claude Code や Codex に渡します。
# 実装指示: 問い合わせフォーム・LINE 連携付きの企業サイトを作る
このファイルの指示に従って実装してください。分からない点は実装前に質問してください。
## 概要
- 教材: https://omochix.com/learn/practice/corporate-site-contact-line/
- 難易度: 中級 / 所要 約180分
- 対応AI: Claude Code / Cursor
- 使用技術: LINE Messaging API / Next.js / TypeScript / Vercel
- 最終検証日: 2026-10-21
## 作るもの
トップ・サービス・会社情報・お問い合わせ・プライバシーポリシーの 5 ページ。問い合わせフォームを送ると、管理者のメールと LINE 公式アカウントに 1 通ずつ通知が届く。Vercel で公開済み。
## 前提条件
- GitHub アカウント
- Vercel アカウント(無料枠でよい)
- LINE Developers のプロバイダーと Messaging API チャネル(無料)
- Resend のアカウント(無料枠でよい。別のメール送信サービスでも可)
- Node.js 20 以上と、Claude Code か Cursor
## 動作確認環境
- Node.js 20
- Next.js 15(App Router)
- Vercel(2026年10月時点の無料枠)
- LINE Messaging API(push message)
- Resend(メール送信)
## 実装手順
### STEP 1: 作りたいものを 1 文で決める
「誰のための、何をしてもらうサイトか」を 1 文にします。例:小さなデザイン事務所が、見積もりの問い合わせをもらうためのサイト。
- 確認: 1 文で言えたら次へ
### STEP 2: AI に情報設計を出してもらう
1 文をプロンプトに入れて、5 ページの見出し構成とフォーム項目を出してもらいます。分からない点は推測させず、質問として返してもらいます。
AI に渡すプロンプト(要件を 1 文から情報設計にする):
```text
あなたは Web 制作者です。次の 1 文から、企業サイトの情報設計を提案してください。
作りたいもの: <ここに 1 文。例: 小さなデザイン事務所の、問い合わせをもらうためのサイト>
出力:
- 5 ページ(トップ / サービス / 会社情報 / お問い合わせ / プライバシーポリシー)それぞれの目的と見出し構成
- トップに載せる要素の優先順位
- 問い合わせフォームの項目(必須 / 任意)
- まだ決まっていないことの質問リスト(推測で埋めない)
```
- 確認: 5 ページの見出しとフォーム項目が決まった
### STEP 3: プロジェクトを作って GitHub に置く
npx create-next-app@latest でプロジェクトを作り、最初のコミットを GitHub に置きます。手順は AI で 0 から Web サービスを公開する の STEP 4〜15 と同じです。
- 確認: GitHub にリポジトリができた
### STEP 4: 静的サイトの骨子を作る
5 ページと共通ヘッダー・フッターを作ってもらいます。文章はあとで差し替えるので、まずは構造と見た目だけを整えます。
AI に渡すプロンプト(静的サイトの骨子を作る):
```text
Next.js(App Router)で 5 ページの静的な企業サイトを作ってください。
条件:
- ページ: / , /services , /company , /contact , /privacy
- 共通ヘッダー(ロゴ・ナビ)と共通フッター(会社名・プライバシーポリシーへのリンク)
- CSS はフレームワークを使わず、CSS Modules か素の CSS。色は --primary: #6e4bff を基調に
- 画像はプレースホルダーでよい(alt は必ず付ける)
- スマートフォン幅(375px)で崩れないこと
- 各ページの title と description を設定すること
作ったら、起動コマンドと確認手順を最後に書いてください。
```
- 確認: 5 ページが表示され、375px で崩れない
### STEP 5: 問い合わせフォームと API ルートを作る
フォームと受け口の API を作ります。この段階では通知を送らず、受け付けた内容をサーバーのログに出すだけにして、検証とレート制限が効くことを先に確かめます。
AI に渡すプロンプト(問い合わせフォームと API ルート):
```text
/contact に問い合わせフォームを作り、送信先として API ルート app/api/contact/route.ts を作ってください。
フォーム:
- 項目: お名前(必須)、メールアドレス(必須・形式チェック)、お問い合わせ内容(必須・最大 2000 文字)
- ハニーポット用の非表示項目(入力があれば受け付けない)
- 送信中はボタンを無効化し、成功 / 失敗をテキストで表示(aria-live="polite")
API:
- POST のみ。JSON を受け取り、サーバー側でも同じ検証を行う
- 同じ IP から 1 分に 3 回を超えたら 429 を返す(メモリ上の簡易制限でよい)
- 成功したら { ok: true } を返す。通知の送信は次のステップで実装するので、いまは console.log で内容を出すだけにする
- 秘密情報は一切ハードコードしない
```
コード例(app/api/contact/rate-limit.ts):
```typescript
const hits = new Map<string, number[]>();
export function tooMany(ip: string, limit = 3, windowMs = 60_000) {
const now = Date.now();
const recent = (hits.get(ip) ?? []).filter((t) => now - t < windowMs);
recent.push(now);
hits.set(ip, recent);
return recent.length > limit;
}
```
- 確認: 空送信が拒否され、連打すると 429 になる
### STEP 6: LINE Developers でチャネルを用意する
LINE Developers コンソールでプロバイダーと Messaging API チャネルを作り、チャネルアクセストークン(長期)を発行します。通知先は自分のユーザー ID(チャネル基本設定の「あなたのユーザー ID」)です。公式アカウントを友だち追加しておきます。
トークンは .env に書きます。.env.example にはキー名とプレースホルダーだけを書きます。
コード例(.env.example):
```bash
# 実際の値は .env(git には入れない)と Vercel の環境変数にだけ置く
RESEND_API_KEY=<ここに貼る:Resend の API キー>
CONTACT_TO=<ここに貼る:通知を受け取るメールアドレス>
CONTACT_FROM=<ここに貼る:Resend で認証した差出人>
LINE_CHANNEL_ACCESS_TOKEN=<ここに貼る:LINE Developers のチャネルアクセストークン>
LINE_TO=<ここに貼る:通知先の LINE ユーザー ID>
```
- 確認: .env にトークンがあり、.env.example には実際の値が無い
### STEP 7: メールと LINE に通知する
API ルートに通知処理を足します。環境変数が無いときは落ちずにスキップし、片方が失敗してももう片方は送るようにします。
AI に渡すプロンプト(メールと LINE への通知):
```text
app/api/contact/route.ts に、受け付けた問い合わせを 2 か所へ通知する処理を追加してください。
1. メール: Resend の SDK で管理者宛に送る。API キーは環境変数 RESEND_API_KEY、宛先は CONTACT_TO、差出人は CONTACT_FROM
2. LINE: Messaging API の push message で、環境変数 LINE_CHANNEL_ACCESS_TOKEN と LINE_TO(通知先のユーザー ID)を使って送る。本文は「お名前 / メール / 内容の先頭 200 文字」
条件:
- 環境変数は process.env から読み、未設定のときは 500 ではなく「設定が足りません」とログに出して { ok: false } を返す
- トークンや宛先をコードや .env.example に実際の値で書かない。.env.example にはキー名とプレースホルダー(<ここに貼る:…>)だけを書く
- 片方の送信が失敗しても、もう片方は送る
- 個人情報をログに残さない(名前・メール・本文をそのまま console.log しない)
```
コード例(app/api/contact/line.ts):
```typescript
export async function notifyLine(text: string) {
const token = process.env.LINE_CHANNEL_ACCESS_TOKEN;
const to = process.env.LINE_TO;
if (!token || !to) {
console.warn('LINE notification skipped: environment is not configured');
return false;
}
const res = await fetch('https://api.line.me/v2/bot/message/push', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ to, messages: [{ type: 'text', text: text.slice(0, 1000) }] }),
});
return res.ok;
}
```
- 確認: テスト送信でメールと LINE に 1 通ずつ届く
### STEP 8: プライバシーポリシーに通知先を書く
問い合わせ内容を「メールと LINE で運営者に通知し、サーバーには保存しない」ことをプライバシーポリシーに明記します。文面は運営者が確認してから公開します。
- 確認: 通知先と保存しない旨が書かれている
### STEP 9: 公開前チェックを AI に出してもらう
秘密情報の混入、検証、レート制限、表示崩れを表で確認します。問題があればその場で直します。
AI に渡すプロンプト(公開前のセルフチェック):
```text
このプロジェクトを公開する前に、次を確認して結果を表にしてください。
- .env が .gitignore に入っていて、git ls-files .env が空
- .env.example に実際の値が入っていない
- API ルートで入力を検証している(必須・長さ・メール形式・ハニーポット・レート制限)
- 問い合わせ内容を永続化していない(通知だけ)
- プライバシーポリシーに「問い合わせ内容をメールと LINE で運営者に通知する」ことが書いてある
- 375px で全ページが崩れない
- 各ページに title と description がある
問題があれば、修正案も一緒に出してください。
```
- 確認: 表のすべてが OK
### STEP 10: Vercel に公開する
Vercel でリポジトリを取り込み、環境変数(5 つ)を Vercel 側に登録してからデプロイします。公開 URL でフォームを 1 回送信し、通知が届くことを確かめます。
- 確認: 公開 URL からの送信でメールと LINE に届く
## 検証
- フォーム送信で通知が届く — やり方: 公開 URL からテスト送信する / 期待結果: メールと LINE 公式アカウントに 1 通ずつ届き、本文に名前・メール・内容の先頭が含まれる
- 空送信・不正なメールが拒否される — やり方: 必須項目を空にして送る。メール欄に abc と入れて送る / 期待結果: 送信されず、エラー文が表示される(画面と API の両方で拒否)
- 連打がブロックされる — やり方: 1 分以内に 4 回送る / 期待結果: 4 回目は 429 になり、通知は 3 通まで
- ハニーポットが効く — やり方: 開発者ツールで非表示項目に文字を入れて送る / 期待結果: 受け付けられず、通知も届かない
- 秘密情報が git に入っていない — やり方: git ls-files .env を実行し、.env.example を開く / 期待結果: 何も表示されず、.env.example はプレースホルダーだけ
- 環境変数なしで落ちない — やり方: ローカルで .env を外して送信する / 期待結果: 500 にならず、ログに「設定が足りません」と出る
- 個人情報がログに出ない — やり方: Vercel のログを見る / 期待結果: 名前・メール・本文がそのまま出ていない
- 375px で崩れない — やり方: 端末エミュレーションで 5 ページを見る / 期待結果: 横スクロールが出ず、フォームが押せる
## 安全性・秘密情報
- チャネルアクセストークンとメール API キーは .env と Vercel の環境変数にだけ置く。コード・コミット・このページには書かない
- .env を .gitignore に入れ、公開前に git ls-files .env が空であることを確認する
- LINE API はブラウザから直接叩かず、必ずサーバー(API ルート)から送る
- 入力はサーバー側でも検証し、ハニーポットとレート制限で迷惑送信を減らす
- 問い合わせ内容はサーバーに保存せず通知だけにし、プライバシーポリシーに通知先を書く
- ログに個人情報(名前・メール・本文)をそのまま出さない
- 「<ここに貼る:…>」の形のプレースホルダーは、環境変数など公開されない場所に実際の値を置き、コードやリポジトリに書かない
## 公開手順
- Vercel で GitHub リポジトリを取り込む
- Vercel の Environment Variables に .env.example の 5 項目を登録する(Production)
- デプロイ後、公開 URL から 1 回テスト送信して通知を確認する
- 独自ドメインを設定し、HTTPS になっていることを確認する
- Search Console にサイトを登録する
## よくあるエラー
- 送信しても LINE に届かない — 原因: LINE_TO が自分のユーザー ID ではない、または公式アカウントを友だち追加していない。トークンの期限切れや Vercel に環境変数を登録していないことも多い / 対処: LINE Developers の「あなたのユーザー ID」を LINE_TO に入れ、公式アカウントを友だち追加する。Vercel の環境変数を確認して再デプロイする
- メールは届くのに LINE だけ失敗する(401) — 原因: チャネルアクセストークンが間違っている、または別チャネルのもの / 対処: LINE Developers で長期トークンを再発行し、.env と Vercel の両方を更新する
- ローカルでは届くのに公開後は届かない — 原因: .env は git に入れていないので、Vercel 側に環境変数が無い / 対処: Vercel の Environment Variables に 5 項目を登録して再デプロイする
- 正しい入力でも 429 になる — 原因: レート制限の窓(1 分 3 回)にテスト送信が引っかかっている / 対処: 1 分待つか、開発中だけ上限を上げる。本番の値は戻す
- GitHub にトークンを push してしまった — 原因: .env をコミットした、またはコードに直書きした / 対処: すぐに LINE Developers と Resend でトークンを無効化・再発行し、履歴から削除する。再発行しない限り漏れたトークンは使われ続ける
## 参照した公式仕様
- LINE Messaging API リファレンス(プッシュメッセージ) https://developers.line.biz/ja/reference/messaging-api/#send-push-message
- Next.js Route Handlers https://nextjs.org/docs/app/building-your-application/routing/route-handlers
- Vercel Environment Variables https://vercel.com/docs/projects/environment-variables
- Resend Node.js SDK https://resend.com/docs/send-with-nodejs
## 受け入れ条件
- 上の検証項目がすべて期待結果どおりになる
- 秘密情報がコード・設定ファイル・公開ページに含まれていない
- スマートフォン幅でも表示が崩れず、キーボードだけで操作できる
# 要件を 1 文から情報設計にする
あなたは Web 制作者です。次の 1 文から、企業サイトの情報設計を提案してください。
作りたいもの: <ここに 1 文。例: 小さなデザイン事務所の、問い合わせをもらうためのサイト>
出力:
- 5 ページ(トップ / サービス / 会社情報 / お問い合わせ / プライバシーポリシー)それぞれの目的と見出し構成
- トップに載せる要素の優先順位
- 問い合わせフォームの項目(必須 / 任意)
- まだ決まっていないことの質問リスト(推測で埋めない)
---
# 静的サイトの骨子を作る
Next.js(App Router)で 5 ページの静的な企業サイトを作ってください。
条件:
- ページ: / , /services , /company , /contact , /privacy
- 共通ヘッダー(ロゴ・ナビ)と共通フッター(会社名・プライバシーポリシーへのリンク)
- CSS はフレームワークを使わず、CSS Modules か素の CSS。色は --primary: #6e4bff を基調に
- 画像はプレースホルダーでよい(alt は必ず付ける)
- スマートフォン幅(375px)で崩れないこと
- 各ページの title と description を設定すること
作ったら、起動コマンドと確認手順を最後に書いてください。
---
# 問い合わせフォームと API ルート
/contact に問い合わせフォームを作り、送信先として API ルート app/api/contact/route.ts を作ってください。
フォーム:
- 項目: お名前(必須)、メールアドレス(必須・形式チェック)、お問い合わせ内容(必須・最大 2000 文字)
- ハニーポット用の非表示項目(入力があれば受け付けない)
- 送信中はボタンを無効化し、成功 / 失敗をテキストで表示(aria-live="polite")
API:
- POST のみ。JSON を受け取り、サーバー側でも同じ検証を行う
- 同じ IP から 1 分に 3 回を超えたら 429 を返す(メモリ上の簡易制限でよい)
- 成功したら { ok: true } を返す。通知の送信は次のステップで実装するので、いまは console.log で内容を出すだけにする
- 秘密情報は一切ハードコードしない
---
# メールと LINE への通知
app/api/contact/route.ts に、受け付けた問い合わせを 2 か所へ通知する処理を追加してください。
1. メール: Resend の SDK で管理者宛に送る。API キーは環境変数 RESEND_API_KEY、宛先は CONTACT_TO、差出人は CONTACT_FROM
2. LINE: Messaging API の push message で、環境変数 LINE_CHANNEL_ACCESS_TOKEN と LINE_TO(通知先のユーザー ID)を使って送る。本文は「お名前 / メール / 内容の先頭 200 文字」
条件:
- 環境変数は process.env から読み、未設定のときは 500 ではなく「設定が足りません」とログに出して { ok: false } を返す
- トークンや宛先をコードや .env.example に実際の値で書かない。.env.example にはキー名とプレースホルダー(<ここに貼る:…>)だけを書く
- 片方の送信が失敗しても、もう片方は送る
- 個人情報をログに残さない(名前・メール・本文をそのまま console.log しない)
---
# 公開前のセルフチェック
このプロジェクトを公開する前に、次を確認して結果を表にしてください。
- .env が .gitignore に入っていて、git ls-files .env が空
- .env.example に実際の値が入っていない
- API ルートで入力を検証している(必須・長さ・メール形式・ハニーポット・レート制限)
- 問い合わせ内容を永続化していない(通知だけ)
- プライバシーポリシーに「問い合わせ内容をメールと LINE で運営者に通知する」ことが書いてある
- 375px で全ページが崩れない
- 各ページに title と description がある
問題があれば、修正案も一緒に出してください。 参照した公式仕様
更新履歴
- 2026.10.21
- 初版