Client Component
'use client';
import { useState } from 'react';
const endpoint = process.env.NEXT_PUBLIC_FORMBNB_ENDPOINT!;
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'sending' | 'success' | 'error'>('idle');
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
if (status === 'sending') return;
setStatus('sending');
const form = event.currentTarget;
const response = await fetch(endpoint, {
method: 'POST',
body: new FormData(form),
headers: { Accept: 'application/json' },
});
if (response.ok) {
form.reset();
setStatus('success');
} else {
setStatus('error');
}
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit" disabled={status === 'sending'}>
{status === 'sending' ? 'Sending...' : 'Send'}
</button>
{status === 'success' && <p>Thanks. Your message was sent.</p>}
{status === 'error' && <p>Something went wrong.</p>}
</form>
);
}
NEXT_PUBLIC_FORMBNB_ENDPOINT=https://api.formbnb.com/f/YOUR_ORG/YOUR_FORM
Server Action
// app/contact/page.tsx
import { submitContact } from './actions';
export default function ContactPage() {
return (
<form action={submitContact}>
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit">Send</button>
</form>
);
}
// app/contact/actions.ts
'use server';
import { redirect } from 'next/navigation';
export async function submitContact(formData: FormData) {
const response = await fetch('https://api.formbnb.com/f/YOUR_ORG/YOUR_FORM', {
method: 'POST',
body: formData,
headers: { Accept: 'application/json' },
});
if (!response.ok) {
throw new Error('Form submission failed');
}
redirect('/thanks');
}
API Route Proxy
// app/api/contact/route.ts
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
const formData = await request.formData();
const email = formData.get('email');
if (!email || !email.toString().includes('@')) {
return NextResponse.json({ error: 'Invalid email' }, { status: 400 });
}
const response = await fetch('https://api.formbnb.com/f/YOUR_ORG/YOUR_FORM', {
method: 'POST',
body: formData,
headers: { Accept: 'application/json' },
});
const data = await response.json().catch(() => ({}));
return NextResponse.json(data, { status: response.status });
}