← 戻る

Next.js → Astro 移行時のフォームページ実装戦略


概要

Next.js App Router + Firebase → Astro + CF Pages への移行時のフォーム実装パターン。reCAPTCHA v3、Firebase Cloud Functions、HubSpot 埋め込みをどう置き換えるか。

アーキテクチャ変更

要素Next.jsAstro
CAPTCHAreCAPTCHA v3Cloudflare Turnstile
バックエンドFirebase Cloud FunctionsCF Pages Functions (/api/*)
フォーム送信Server Action + FirebaseCF API ルート
HubSpot埋め込み(SSR時にスキップ)React Island化

実装フロー

1. Turnstile の統合

<!-- Astro コンポーネント -->
<div id="turnstile-container"></div>
<script>
  import Turnstile from '@/components/Turnstile.tsx';
</script>
<Turnstile />

2. API ルートの実装

// src/pages/api/submit-form.ts
export async function POST({ request }) {
  const formData = await request.json();

  // Turnstile 検証
  const verifyResponse = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
    method: 'POST',
    body: JSON.stringify({
      secret: import.meta.env.TURNSTILE_SECRET_KEY,
      response: formData.captchaToken
    })
  });

  if (!verifyResponse.ok) {
    return new Response(JSON.stringify({ error: 'Captcha failed' }), { status: 400 });
  }

  // メール送信等の処理
  return new Response(JSON.stringify({ success: true }));
}

3. HubSpot 埋め込みの React Island化

// React コンポーネント
export default function HubSpotForm() {
  useEffect(() => {
    if (window.hbspt) {
      window.hbspt.forms.create({
        region: 'na1',
        portalId: '...',
        formId: '...',
        target: '#hubspot-form'
      });
    }
  }, []);

  return <div id="hubspot-form" />;
}

Astro での使用:

<HubSpotForm client:load />

メリット

  • CF Pages はサーバーレス、メンテナンス不要
  • Turnstile は無料+プライバシー優先
  • Astro + React Island で必要な部分のみインタラクティブ

検討点

  • Firebase から CF Functions への認証情報移行
  • メール送信ロジックの Durable Objects 利用の検討
  • ログ保存先の決定(D1 / Firestore など)