Guide
Formulaire de contact Next.js (sans backend)
Next.js n'a pas besoin de son propre récepteur de formulaire. Vous pouvez déposer le même form action HTML brut dans n'importe quel Server Component, ou - si vous voulez des états succès/erreur côté client - utiliser un petit Client Component avec fetch. Les deux POSTent directement vers Formhook.
Utilisez un formulaire HTML brut
Vous n'avez pas besoin d'une route API. Le formulaire POSTe directement vers Formhook, et votre framework n'a jamais à toucher la soumission.
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST">
<label>
Email
<input type="email" name="email" required />
</label>
<label>
Message
<textarea name="message" required></textarea>
</label>
<!-- honeypot: bots fill this; humans don't see it -->
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" hidden />
<!-- optional: send users to a thank-you page after a native POST -->
<input type="hidden" name="_redirect" value="https://example.com/thanks" />
<button type="submit">Send</button>
</form>Ou envoyez avec fetch dans Next.js
Utilisez cette version si vous voulez des états succès/erreur côté client sans rechargement de page.
"use client";
import { useState } from "react";
export function ContactForm() {
const [status, setStatus] = useState<"idle" | "sending" | "ok" | "error">("idle");
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus("sending");
const form = e.currentTarget;
const data = Object.fromEntries(new FormData(form));
const res = await fetch("https://formhook.app/f/YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
setStatus(res.ok ? "ok" : "error");
if (res.ok) form.reset();
}
if (status === "ok") return <p>Thanks - we'll be in touch.</p>;
return (
<form onSubmit={onSubmit}>
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<input type="text" name="_gotcha" tabIndex={-1} hidden />
<button type="submit" disabled={status === "sending"}>
{status === "sending" ? "Sending…" : "Send"}
</button>
{status === "error" && <p>Something went wrong. Please try again.</p>}
</form>
);
}Comment ça marche
Le form action simple fonctionne dans n'importe quelle page ou layout Next.js, y compris les Server Components. Pas de app/api/contact/route.ts, pas de Server Action, pas de middleware. Si vous voulez une UX côté client avec états succès/erreur, le deuxième snippet montre le motif canonique : "use client", useState, onSubmit, fetch vers formhook.app/f/YOUR_API_KEY. Le honeypot (_gotcha) et l'optionnel _redirect sont les mêmes champs spéciaux que dans le guide HTML.
Formulaire classique ou fetch : lequel choisir ?
Choisissez le formulaire classique avec action si vous voulez zéro JavaScript : il fonctionne dans un Server Component et continue de marcher même si l'hydratation échoue. Contrepartie : le navigateur quitte votre page à l'envoi, ajoutez donc un champ caché _redirect avec une URL absolue appartenant à l'une de vos origines autorisées, par exemple https://example.com/merci. Sans lui, les visiteurs atterrissent sur une réponse JSON brute.
Choisissez la version fetch quand vous voulez afficher le message de succès ou d'erreur sur place, avec un bouton désactivé pendant l'envoi. Les envois de formulaire classique peuvent rediriger ; les envois JSON via fetch reçoivent une réponse JSON, donc _redirect y est ignoré. Le détail est dans Soumission de formulaire en AJAX.
Corriger l'erreur 403 origin_not_allowed en développement local
Formhook n'accepte les envois depuis un navigateur que pour les origines listées dans Origines autorisées de votre formulaire, et la correspondance est exacte : schéma, hôte et port. http://localhost:3000, https://example.com et https://www.example.com sont trois origines différentes. Ajoutez votre URL de développement, votre domaine de production et tout domaine de préproduction sur lequel vous testez, sans chemin ni barre oblique finale. Une liste vide rejette toutes les requêtes de navigateur.
Si un envoi échoue malgré tout, le corps de la réponse en donne la raison : origin_not_allowed (403) signifie que l'origine manque dans la liste, form_not_found (404) que la clé d'API est incorrecte, et rate_limited (429) qu'il faut attendre le nombre de secondes indiqué par Retry-After. Plus de détails dans Formulaire de contact en panne ?
Où placer la clé d'API
La clé se retrouve de toute façon dans votre HTML ou votre bundle JavaScript : considérez-la comme un identifiant public, pas comme un secret. Une variable d'environnement NEXT_PUBLIC_FORMHOOK_KEY reste pratique pour utiliser un formulaire en développement et un autre en production.
Ce qui protège le formulaire se trouve du côté de Formhook : la liste des origines autorisées, le honeypot _gotcha, les limites de débit par IP et par formulaire, et Cloudflare Turnstile en option. La liste d'origines empêche d'autres sites de poster depuis un navigateur, mais ce n'est pas une authentification, car un script peut envoyer n'importe quel en-tête Origin. Pour les bots, comptez sur les couches anti-spam ; la protection anti-spam des formulaires de contact les compare.
Envoyer depuis une Server Action à la place
Si vous voulez ajouter des données côté serveur ou valider avant l'envoi, appelez Formhook depuis une Server Action ou un route handler. Les requêtes serveur n'envoient pas d'en-tête Origin : elles doivent donc porter un en-tête X-Auth-Token, généré dans les paramètres de votre formulaire. Gardez ce jeton dans une variable d'environnement réservée au serveur, jamais dans un Client Component. La plupart des formulaires de contact n'en ont pas besoin, c'est pourquoi les snippets ci-dessus s'en passent. Le format complet des requêtes figure dans la documentation.
Avant la mise en ligne
- Ajoutez l'origine de production, avec
https://, aux origines autorisées. - Gardez le champ honeypot
_gotchaet décidez si vous activez Turnstile. - Envoyez un test et vérifiez qu'il apparaît dans le tableau de bord et comme notification push.
- Ajoutez une courte mention de confidentialité sous le formulaire. Le guide du formulaire de contact conforme au GDPR propose des formulations à adapter.
Ce qui se passe ensuite
- La soumission apparaît dans votre tableau de bord Formhook en moins d'une seconde.
- Une notification push se déclenche sur chaque appareil où vous l'avez activée.
- Répondez directement depuis le tableau de bord (Pro et au-dessus) - pratique pour les missions client où chaque projet a sa propre route de contact.
Lancez votre formulaire de contact Next.js aujourd'hui.
Inscrivez-vous gratuitement, créez un formulaire, collez la clé API. Cinq minutes.
Commencer gratuitementNiveau gratuit : 5 formulaires · 250 soumissions/mois · Sans carte bancaire.
Formulaire de contact Next.js - FAQ
Dois-je ajouter une route API ou une Server Action ?
Puis-je utiliser ceci dans un Server Component ?
Comment gérer le spam sans écrire de middleware de rate-limiting ?
Guides pour les autres frameworks
Migrating from Formspree? See how Formhook compares.