ポートフォリオ標準構成への再設計 + SES 通知稼働

インフラ・CI/CD・監視がすべて整ったところで、最後の仕上げ 「サイトの構造を ポートフォリオ向けに再設計」 + 「SES sandbox から問い合わせメール送信稼働まで」 を 1 記事にまとめます。本シリーズの最終構築回。

サイト UX の再設計 — Web 調査から

当初、トップページは 「テスト ページ + 問い合わせフォーム + 解説書リンク」 という構造でした。これだと「インフラはちゃんとしてるけど、サイト自体は雑」な印象に。フリーランスのポートフォリオなら、サイト構造そのもの も評価対象になります。

そこで Web 検索でフリーランスエンジニアの標準的なサイト構成を調査:

これがフリーランス・エンジニアサイトの黄金パターンと判明。本シリーズでも採用しました。

本サイトの構成(再設計後)

セクション内容
Heroキャッチコピー + 「実績を見る」「お問い合わせ」「解説書を読む」3 つの CTA
About専門領域・働き方・所在の概要カード
Skills6 カテゴリ × タグクラウド(AWS / IaC / Linux / アプリ / 観測 / セキュリティ)
Worksiigtn-platform を最初の実績として、今後追加予定の枠付き
Blog本シリーズへのリンク
Contact問い合わせフォーム(既存の API GW + Lambda + DDB に接続)

Sticky なナビゲーションを上に固定して、各セクションへ anchor リンクで飛べる構造に。スマホでも Nav が flex-wrap で折り返す。

Hero のデザイン

シンプルな 1 文字モノグラム("i")+ キャッチコピーで構成:

<section class="hero">
  <div class="hero-monogram">i</div>
  <h1>サーバレス × IaC で<br>
      動かし続ける <span class="accent">インフラ</span> を。</h1>
  <p class="tagline">
    AWS / Linux / Terraform を軸に、フリーランス・インフラエンジニアとして…
  </p>
  <div class="hero-cta">
    <a href="#works" class="btn btn-primary">実績を見る</a>
    <a href="#contact" class="btn btn-ghost">お問い合わせ</a>
    <a href="/learn.html" class="btn btn-ghost">解説書を読む →</a>
  </div>
</section>

顔写真の代わりにモノグラム使用。CSS の linear-gradient + box-shadow で「ちゃんと作った感」を出す。

Skills セクション

カテゴリ別にカードを並べ、タグクラウドで表現:

<div class="skill-card">
  <h3>☁️ AWS</h3>
  <ul class="skill-tags">
    <li class="skill-tag">CloudFront</li>
    <li class="skill-tag">S3</li>
    <li class="skill-tag">Lambda</li>
    ...
  </ul>
</div>

カテゴリは 6 個(AWS / IaC・自動化 / Linux・ネットワーク / アプリ・言語 / 観測・運用 / セキュリティ)。1 カード = 1 専門領域で見せる。

SES 通知の有効化

サイト構造ができたところで、最後に問い合わせフォームの メール送信 を有効化しました。Lambda コードは最初から SES 対応済でしたが、SES の Identity verify と環境変数設定が必要。

SES sandbox の制約

新規 AWS アカウントの SES は sandbox 状態 で始まります:

個人ポートフォリオの問い合わせ流量なら十分すぎる。本番化したい時は Production Access 申請(1〜2 営業日)で解除可能。

verify の手順

contact@iigtn.com を SES に Identity 登録:

aws sesv2 create-email-identity \
  --region ap-northeast-1 \
  --email-identity contact@iigtn.com

これで AWS から「Amazon Web Services – Email Address Verification Request」のメールが contact@iigtn.com に届く。「Verify this email address」リンクをクリック すると verify 完了。

aws sesv2 get-email-identity \
  --region ap-northeast-1 \
  --email-identity contact@iigtn.com \
  --query 'VerificationStatus'
# "SUCCESS"

Lambda 環境変数の更新

Terraform の tfvars に SES 設定を追加:

# terraform/envs/prod/terraform.tfvars
ses_from = "contact@iigtn.com"
ses_to   = "contact@iigtn.com"

terraform apply で Lambda の環境変数 SES_FROM / SES_TO が更新されます。

動作確認

# 本番フォーム経由でテスト送信
curl -X POST "https://lab.iigtn.com/api/contact" \
  -H "Content-Type: application/json" \
  -d '{"name":"Test","email":"a@b.com","message":"SES verification test"}'
# {"ok":true}

# SES の送信実績確認
aws sesv2 get-account --region ap-northeast-1 \
  --query 'SendQuota'
# {
#   "Max24HourSend": 200.0,
#   "MaxSendRate": 1.0,
#   "SentLast24Hours": 1.0  ← 1 通送信実績
# }

contact@iigtn.com の受信ボックスにメールが届けば成功:

From: contact@iigtn.com
To:   contact@iigtn.com
Subject: [iigtn] New contact: Test

New contact submission
ID: <UUID>
Time: 2026-04-26T13:00:00.000Z
Name: Test
Email: a@b.com
Source IP: ...

Message:
SES verification test

Lambda コードの SES 連携

Lambda 内では try/catch で SES エラーを吸収:

// SES でメール送信 (失敗しても致命的扱いはしない)
if (SES_FROM && SES_TO) {
  try {
    await sesClient.send(new SendEmailCommand({
      FromEmailAddress: SES_FROM,
      Destination: { ToAddresses: [SES_TO] },
      Content: {
        Simple: {
          Subject: { Data: `[iigtn] New contact: ${item.name}`, Charset: "UTF-8" },
          Body:    { Text: { Data: emailBody, Charset: "UTF-8" } },
        },
      },
    }));
  } catch (err) {
    // sandbox 制限などで送信失敗 → ログだけ残し、フロントには成功扱い
    console.warn("SES SendEmail failed (continuing)", { id, err: err.message });
  }
}

SES が落ちても DDB には保存される。フォームの体験を壊さない設計。

本シリーズで完成したもの全部

領域状態
Terraform モジュール 5 個✅ network_dns / frontend_cdn / backend_api / ci_oidc / observability
静的サイト✅ S3 + CloudFront + OAC + ACM
動的 API✅ API Gateway + Lambda + DynamoDB
CI/CD✅ GitHub Actions OIDC(静的キーレス)
監視✅ CloudWatch Alarms + SNS(ap-northeast-1 + us-east-1)
予算アラート✅ AWS Budgets 3 段階通知
メール通知✅ SES(sandbox 内、contact@iigtn.com 宛)
解説書✅ /learn.html(インライン drawio 図 4 個)
サイト UX✅ Hero / About / Skills / Works / Blog / Contact
ブログシリーズ✅ 全 21 記事(このシリーズ)

これから追加していく予定

シリーズ振り返り

本シリーズは個人サイト 1 つを構築する記録ですが、書いてみて気付いたのは 「設計 / 実装 / 運用 / 観測 / ドキュメント / UX のすべてを通しでやる経験」が、案件で一番効く ということ。

1 つの技術を深く知ることも大事ですが、フリーランスとしてクライアントに提案するなら、「全部繋がる経験」 こそが信用になります。

最後に

本シリーズで使った全リソースの 月額コストは約 200 円。1 万円の本を 1 冊買うより安い金額で、AWS / Terraform / GitHub Actions の実戦経験が手に入ります。

「やってみたい」と思ったら、まず最小構成(S3 + CloudFront)から始めれば 1 日でサイトが立ちます。本シリーズが、その最初の一歩の参考になれば嬉しいです。

次の記事(最終回)

次は本シリーズの 付録: 構築で使ったコマンド早見表。PowerShell / Git / AWS CLI / Terraform / curl / npm 等の頻出コマンドを 1 ページにまとめます。手元に置いてリファレンスとして使えます。

📚 用語集

Hero (ファーストビュー)
サイトのトップで最初に表示されるエリア。キャッチコピー + メイン画像 + CTA で訪問者を引き込む。
CTA (Call To Action)
「行動を促すボタン・リンク」。「実績を見る」「お問い合わせ」「資料請求」等。Hero に複数置くのが定番。
About セクション
「私は誰で、何ができるか」を伝えるエリア。プロフィール・写真・経歴・価値観等。
Skills セクション
技術スタック・スキルセットを提示するエリア。タグクラウド形式が見やすい。
Works (実績・制作物)
これまでの制作・案件を紹介するエリア。3〜5 件のケーススタディが推奨。
Blog セクション
継続的な発信の場。技術ブログ / 月次運用レポート / Post-mortem 等を載せる。
Contact セクション
問い合わせフォーム。フリーランスサイトでは案件相談の導線として最重要。
sticky navigation
スクロールしても画面上部に固定されるナビゲーション。CSS の position: sticky で実現。
SES (Simple Email Service)
AWS のメール送信サービス。sandbox 状態と Production 状態がある。
SES sandbox
新規アカウントの SES の初期状態。送信元 / 送信先の verify 必須・1 日 200 通までの制限。
SES Production Access
SES sandbox から本番モードへの移行。AWS にユースケース説明を申請して承認を得る(1〜2 営業日)。
Email Identity (SES)
SES に登録するメールアドレスや送信ドメイン。verify 完了で送信元 / 送信先として使える。
SendEmail / SendRawEmail (SES API)
SES のメール送信 API。SendEmail はシンプル、SendRawEmail は MIME 全制御。本シリーズでは SESv2 の SendEmail を使用。
SendQuota
SES の送信制限。Max24HourSend(1 日上限)/ MaxSendRate(1 秒上限)/ SentLast24Hours(実績)。
DKIM (DomainKeys Identified Mail)
送信ドメイン認証の仕組み。SES でドメイン verify する時に必要。Squarespace 等で TXT レコードを追加。
SPF (Sender Policy Framework)
送信元 IP の正当性を DNS で宣言する仕組み。SES 利用時は SPF レコードに include:amazonses.com を追加。