Integrate a subscription form in Next.js with a BFF route: the browser posts to your app; your route calls Mailoo with server-held credentials. Prefer @mailoo/forms. For the API contract, see website-forms{.interpreted-text role="doc"}.
Prerequisites
- A Mailoo project with a Form (
FORM) integration - An API key with
webhook.form-submission(or FULL)
Environment (server-only)
@mailoo/forms defaults to the env prefix MAILOO_CONTACT_FORM_INTEGRATION for FORM integrations. The name is historical: it is not the CONTACT_FORM (feedback) integration. Feedback uses MAILOO_FEEDBACK_INTEGRATION --- see feedback-form-nextjs-example{.interpreted-text role="doc"}.
Add to .env.local (or your host secrets):
MAILOO_CONTACT_FORM_INTEGRATION_API=https://api.mailoo.app
MAILOO_CONTACT_FORM_INTEGRATION_API_KEY=your-api-key-here
MAILOO_CONTACT_FORM_INTEGRATION_PROJECT_UID=your-project-uid-here
MAILOO_CONTACT_FORM_INTEGRATION_ID=your-form-integration-id-here
All four are required for the default prefix. Do not use NEXT_PUBLIC_* for the API URL or key. For a second FORM integration, pass a custom prefix (or getConfig) to the route factory.
BFF route handler
// app/api/v1/webhooks/forms/submit/route.ts
import { createFormSubmitHandler } from '@mailoo/forms/routes'
export const POST = createFormSubmitHandler()
Client form
Post to your BFF. Body fields for FORM: email (required), optional name, subject, content, source, metadata. Use content (not message) if you want a custom inbox body.
With the package hook:
'use client'
import { useMailooFormSubmit } from '@mailoo/forms/hooks'
export function NewsletterForm() {
const { submit, loading, error } = useMailooFormSubmit({
endpoint: '/api/v1/webhooks/forms/submit',
})
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
const fd = new FormData(e.currentTarget)
await submit({
email: String(fd.get('email') || '').trim(),
name: String(fd.get('name') || '').trim() || undefined,
source: typeof window !== 'undefined' ? window.location.href : '',
})
}
return (
<form onSubmit={onSubmit}>
<input name="name" placeholder="Your name (optional)" disabled={loading} />
<input name="email" type="email" required disabled={loading} />
<button type="submit" disabled={loading}>
{loading ? 'Subscribing…' : 'Subscribe'}
</button>
{error ? <p>{error}</p> : null}
</form>
)
}
Or call fetch yourself with the same JSON shape.
Related
website-forms{.interpreted-text role="doc"} --- endpoint and subscriber behaviourfeedback-form-nextjs-example{.interpreted-text role="doc"} --- CONTACT_FORM / feedbacknextjs-packages{.interpreted-text role="doc"} --- package overview