Formulaire de contact
Onyx inclut un formulaire de contact complet avec validation côté client et envoi d'email via Resend. Deux variables d'environnement suffisent pour l'activer.
Comment ça fonctionne
Quand l'utilisateur soumet le formulaire, voici ce qui se passe :
- →Validation client — react-hook-form + zod valident les champs avant envoi
- →API Route — La requête POST est envoyée à /api/contact
- →Resend — Le serveur appelle l'API Resend pour envoyer l'email
- →Toast — Un message de confirmation ou d'erreur apparaît via sonner
Variables d'environnement
Créez un fichier .env.local à la racine du projet et renseignez ces deux variables :
# Clé API obtenue sur resend.com RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxx # Adresse qui recevra les messages CONTACT_EMAIL=vous@votredomaine.fr
Ajouter le formulaire dans une page
Le bloc ContactFormSection est disponible dans src/components/blocks/contact-form-section.tsx. Importez-le dans n'importe quelle page :
import { ContactFormSection } from "@/components/blocks/contact-form-section"; export default function ContactPage() { return <ContactFormSection />; }
Champs du formulaire
Par défaut, le formulaire comporte trois champs. Pour les modifier, éditez directement src/components/blocks/contact-form-section.tsx.
| Champ | Type | Validation |
|---|---|---|
name | text | Requis, 2 caractères minimum |
email | Requis, format email valide | |
message | textarea | Requis, 10 caractères minimum |
Ajouter un champ
Pour ajouter un champ (ex. : numéro de téléphone), étendez le schéma Zod et le formulaire dans le même fichier :
const contactSchema = z.object({ name: z.string().min(2), email: z.string().email(), phone: z.string().optional(), // nouveau champ message: z.string().min(10), });
src/app/api/contact/route.ts, et de l'ajouter au template HTML de l'email.Route API
La logique serveur est dans src/app/api/contact/route.ts. Elle reçoit le POST, valide les données, et appelle Resend :
import { Resend } from "resend"; const resend = new Resend(process.env.RESEND_API_KEY); export async function POST(req: Request) { const { name, email, message } = await req.json(); await resend.emails.send({ from: "contact@votredomaine.fr", to: process.env.CONTACT_EMAIL, subject: `Message de ${name}`, html: `<p>${message}</p>`, }); }
Protection anti-spam
Onyx inclut un champ honeypot invisible par défaut. Un humain ne le voit pas et ne le remplit jamais. Un bot parcourt le DOM et le remplit automatiquement — la soumission est alors silencieusement ignorée côté serveur, sans révéler la détection.
Pour la grande majorité des sites vitrines, ce mécanisme suffit : il bloque 99 % des spambots génériques sans aucune clé API ni friction pour l'utilisateur.
Aller plus loin avec un CAPTCHA
Si votre site reçoit un volume important de soumissions ou devient une cible connue, ajoutez un CAPTCHA. Les trois options les plus courantes :
| Solution | UX | Prix | Notes |
|---|---|---|---|
| Cloudflare Turnstile | Invisible | Gratuit | Recommandé — zéro friction, RGPD-friendly, pas de cookies |
| hCaptcha | Challenge visuel | Gratuit (limité) | Open source, privacy-first, alternative à reCAPTCHA |
| Google reCAPTCHA v3 | Invisible (score) | Gratuit | Score de confiance 0-1, pas de challenge visible |
TURNSTILE_SECRET_KEY dans .env.local et vérifiée côté serveur dans la route API avant d'envoyer l'email.” L'IA génère l'intégration complète en quelques secondes — pensez à préciser que la clé ne doit jamais être exposée côté client.Tester en développement
Sans RESEND_API_KEY, la route API retourne une erreur 500. Pour tester l'interface sans envoyer d'email, deux options :
- →Resend sandbox — En mode test (clé préfixée re_test_), les emails sont interceptés dans le dashboard Resend sans être livrés
- →Console log — Commentez l'appel Resend et remplacez-le par un console.log() pour tester la validation et l'UI