[Astro #23] Netlify Formsでサーバーレスなコンタクトフォームをゼロから構築する
はじめに
前回の「#22 Netlify CLIを使ったローカルでのデプロイテスト」に引き続き、今回はNetlifyの環境を活かして、サイト内にコンタクトフォーム(通信インターフェース)を実装していく。
[Astro #22] CIを捨ててローカルデプロイへ:Netlify CLIで手に入れる確実性とスピード // PROTOCOL.LAIN
外部サーバーの機嫌に左右されるCI環境を脱却し、Netlify CLIを使用して手元の環境から直接デプロイする方法を解説。確実なビルドとデプロイ速度の向上を実現します。
lain-lab.com静的サイトジェネレーター(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>
重要な属性と隠しフィールド
通常のHTMLフォームと違うのは以下の点だ。
data-netlify="true": デプロイ時にNetlifyのボットがこの属性を検知し、自動的にフォームのエンドポイントを生成してくれる。<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がバイパスされ、ブラウザ本来の標準的な画面遷移が行われるため、エラーを完全に防ぐことができる。
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にデプロイし、実際にブラウザから送信テストを行う。
ログの確認
Netlifyのダッシュボードにログインし、該当プロジェクトの 「Forms」 メニューを開く。 成功していれば、「Active forms」に 「contact」 というフォームが認識され、そこに送信内容(ログ)が蓄積されていく。Freeプランでも月に100件まで受信可能だ。
メール通知(Email notification)の設定
毎回Netlifyの管理画面を見に行くのは非効率なので、メッセージが届いたら指定のメールアドレスに転送されるように設定する。
Site settings>Forms>Form notificationsを開く。
Add notificationから 「Email notification」 を選択。
Formに「contact」を選択し、通知先のメールアドレスを入力する。- Custom email subject line (optional) に
[PROTOCOL.LAIN] コンタクト通知など、特定の件名を設定しておく。
カスタム件名を設定しておけば、メーラー側で自動的にフォルダ振り分けなどのフィルターを組むことができ、管理が格段に楽になる。
まとめ
バックエンドのサーバーを立てずとも、AstroとNetlifyの組み合わせだけで、堅牢で実用的なコンタクトフォームを実装することができた。
情報の海を漂うサイトにおいて、外部(Wired)からのノイズを受信するインターフェースが整ったことになる。これで心置きなく、日々の開発記録のアーカイブに戻ることができそうだ。