[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築する

[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築する

はじめに

前回の「#22 Netlify CLIを使ったローカルでのデプロイテスト」に引き続き、今回はNetlifyの環境を活かして、サイト内にコンタクトフォーム(通信インターフェース)を実装していく。

静的サイトジェネレーター(SSG)であるAstroは、基本的にバックエンドのサーバーを持たない。しかし、Netlifyを利用してホスティングしている場合、Netlify Formsという機能を使うことで、自分でPHPやNode.jsなどのサーバーサイド処理を書くことなく、HTMLの記述だけでフォームを稼働させることができる。

今回は、Astro環境特有の注意点(View Transitionsとの競合など)も含め、ゼロからフォームを構築し、メール通知を受け取るまでのプロトコルを記録しておく。

1. フォームの基本実装(Astroコンポーネント)

まずはフォーム本体のコードから。 Astroのコンポーネント(またはページ)に、以下のようなHTMLを記述する。

<form name="contact" method="POST" data-netlify="true" action="/success" data-astro-reload>
  <input type="hidden" name="form-name" value="contact" />

  <div class="form-group">
    <label>[ NAME ]</label>
    <input type="text" name="name" required placeholder="Authorize Name..." />
  </div>

  <div class="form-group">
    <label>[ EMAIL ]</label>
    <input type="email" name="email" required placeholder="Input Email Address..." />
  </div>

  <div class="form-group">
    <label>[ MESSAGE ]</label>
    <textarea name="message" rows="20" required placeholder="Type your mission status..."></textarea>
  </div>

  <button type="submit" class="submit-btn">EXECUTE</button>
</form>
[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: 1. フォームの基本実装(Astroコンポーネント)

重要な属性と隠しフィールド

通常のHTMLフォームと違うのは以下の点だ。

  1. data-netlify="true": デプロイ時にNetlifyのボットがこの属性を検知し、自動的にフォームのエンドポイントを生成してくれる。
  2. <input type="hidden" name="form-name" value="contact" />: AstroなどのSSGを使っている場合、JavaScriptによるルーティングが介入するため、Netlify側に「どのフォームからの送信か」を伝えるこの隠しフィールドが必須になる。

2. Astro特有の罠:View Transitionsとの衝突

フォームの送信先として action="/success" を指定しているが、ここでAstroの View Transitions を有効にしていると、送信時にコンソールに以下のようなエラーが出ることがある。

Uncaught (in promise) InvalidStateError: Transition was aborted because of invalid state

これは、Netlify側のサーバー主導のリダイレクト処理と、Astroのクライアントサイド・ルーティング(非同期での画面遷移)が衝突して起きるエラーだ。

これを回避するために、formタグに data-astro-reload 属性を付与している。これにより、このフォームの送信時だけはAstroのView Transitionsがバイパスされ、ブラウザ本来の標準的な画面遷移が行われるため、エラーを完全に防ぐことができる。

[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: 2. Astro特有の罠:View Transitionsとの衝突

3. 送信完了画面(success.astro)の作成

フォームの action 属性に指定した遷移先ページを作成する。 これがないと、Netlifyはデータを受け取った後に遷移先を見つけられず、404 Not found のエラー画面を表示してしまう。

src/pages/success.astro を作成し、世界観に合わせた通信完了画面を実装する。

---
import BaseLayout from '../layouts/BaseLayout.astro';
---

<BaseLayout title="SUCCESS // PROTOCOL.LAIN">
  <section class="success-container">
    <h2>> COMMUNICATION_ESTABLISHED</h2>
    <p class="status-text">Your mission status has been synchronized with the Wired.</p>
    <div class="terminal-box">
      <p>[ STATUS ] : SENT</p>
      <p>[ SIGNAL ] : STABLE</p>
    </div>
    <a href="/" class="return-link">RETURN_TO_GATE</a>
  </section>
</BaseLayout>

これで、EXECUTEボタンを押した後に、美学を損なうことなくシームレスに完了画面が表示されるようになる。

4. Netlify管理画面での確認とメール通知設定

コードを git push してNetlifyにデプロイし、実際にブラウザから送信テストを行う。

[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: 4. Netlify管理画面での確認とメール通知設定

ログの確認

Netlifyのダッシュボードにログインし、該当プロジェクトの 「Forms」 メニューを開く。 成功していれば、「Active forms」に 「contact」 というフォームが認識され、そこに送信内容(ログ)が蓄積されていく。Freeプランでも月に100件まで受信可能だ。

[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: 4. Netlify管理画面での確認とメール通知設定(ログの確認)

メール通知(Email notification)の設定

毎回Netlifyの管理画面を見に行くのは非効率なので、メッセージが届いたら指定のメールアドレスに転送されるように設定する。

  1. Site settings > Forms > Form notifications を開く。
[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: メール通知(Email notification)の設定
  1. Add notification から 「Email notification」 を選択。
[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: メール通知(Email notification)の設定
  1. Form に「contact」を選択し、通知先のメールアドレスを入力する。
  2. Custom email subject line (optional) に [PROTOCOL.LAIN] コンタクト通知 など、特定の件名を設定しておく。
[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築: メール通知(Email notification)の設定

カスタム件名を設定しておけば、メーラー側で自動的にフォルダ振り分けなどのフィルターを組むことができ、管理が格段に楽になる。

まとめ

バックエンドのサーバーを立てずとも、AstroとNetlifyの組み合わせだけで、堅牢で実用的なコンタクトフォームを実装することができた。

情報の海を漂うサイトにおいて、外部(Wired)からのノイズを受信するインターフェースが整ったことになる。これで心置きなく、日々の開発記録のアーカイブに戻ることができそうだ。