Integracija pozadinske obrasca Next.js (radnje usmjerivača aplikacije i poslužitelja)
Potpuni vodič za implementaciju TypeScripta i Reacta za rukovanje obrascima za kontakt u Next.js 14/15 koristeći Lugatu krajnje točke i radnje poslužitelja s nultom izloženošću vjerodajnicama.
1. Next.js App Router Arhitektura s radnjama poslužitelja
Akcije poslužitelja Next.js izvršavaju se isključivo na poslužitelju, što ih čini idealnim za slanje upita s privatnim Lugatu API ključevima bez izlaganja tajni u klijentskim paketima.
'use server';
export async function submitContact(prevState: any, formData: FormData) {
// Silent rejection of automated bot submissions via honeypot trap
const honeypot = (formData.get('_gotcha') as string) || '';
if (honeypot) {
return { success: true, error: null };
}
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
if (!name || !email || !message) {
return { success: false, error: 'All fields are required.' };
}
const payload = {
fields: { name, email, message },
};
try {
const res = await fetch(`https://www.lugatu.com/api/v1/forms/${process.env.LUGATU_FORM_ID}/submissions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LUGATU_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify(payload),
});
if (!res.ok) {
return { success: false, error: 'Failed to submit form.' };
}
return { success: true, error: null };
} catch (err) {
return { success: false, error: 'Network error occurred.' };
}
}
2. Komponenta obrasca na strani klijenta sa stanjem učitavanja
Povežite radnju poslužitelja s klijentskom komponentom React 19 / Next.js s dostupnim indikatorima učitavanja.
'use client';
import { useActionState } from 'react';
import { submitContact } from '@/app/actions/contact';
export function ContactForm() {
const [state, formAction, isPending] = useActionState(submitContact, { success: false, error: null });
return (
<form action={formAction} className="space-y-4 max-w-md">
<div>
<label className="block text-sm font-semibold mb-1">Name</label>
<input name="name" required className="w-full border rounded-xl p-2.5" />
</div>
<div>
<label className="block text-sm font-semibold mb-1">Email</label>
<input type="email" name="email" required className="w-full border rounded-xl p-2.5" />
</div>
<div>
<label className="block text-sm font-semibold mb-1">Message</label>
<textarea name="message" rows={4} required className="w-full border rounded-xl p-2.5" />
</div>
<input type="text" name="_gotcha" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
<button type="submit" disabled={isPending} className="btn-primary-editorial w-full py-2.5">
{isPending ? 'Sending...' : 'Send Message'}
</button>
{state.success && <p className="text-emerald-700 text-sm">Thank you! Your message was received.</p>}
{state.error && <p className="text-red-700 text-sm">{state.error}</p>}
</form>
);
}
Sigurnost i provjera autentičnosti
Sigurnosne upute: Nikada ne stavljajte pred LUGATU_API_KEY NEXT_PUBLIC_. Samo privatne varijable na strani poslužitelja mogu sigurno držati vaš živi API ključ.
Rješavanje problema i uobičajene pogreške gutanja
Pozivate fetch() iz koda preglednika na strani klijenta s API ključem. Ili se prebacite na radnju poslužitelja Next.js ili koristite krajnju točku javnog obrasca bez API ključa.
Često postavljana pitanja
Mogu li ovo implementirati na Vercel ili Cloudflare Pages?
Da. Akcije poslužitelja besprijekorno rade na platformama bez poslužitelja i rubnim vremenima izvođenja koje podržava Next.js.
Jeste li spremni za izradu krajnje točke obrasca?
Započnite besplatno za nekoliko sekundi. Kreditna kartica nije potrebna.