Get the next one in your inbox.
One email when we publish something worth reading. No spam — appropriately enough, we'd know.
An honest comparison of writing a Nuxt server route with an email library versus pointing your form straight at a hosted backend like FormBridge — the tradeoff is maintenance, not capability.

Get an instant summary, key takeaways, action items, and answers to your questions about this article.
For a simple contact form, a Nuxt server route with an email library gives full control over sending logic but requires you to manage SMTP credentials and spam handling yourself; pointing the form directly at a hosted backend like FormBridge skips that server route entirely at the cost of a third-party dependency. Both are valid — the real tradeoff is long-term maintenance, not capability.
Nuxt gives you a full server runtime via Nitro, so you can write your own API route to handle a contact form. You can also skip that layer entirely and point the form straight at a hosted form backend. Both are legitimate — the difference is what you're signing up to maintain.
// server/api/contact.post.ts
import nodemailer from 'nodemailer'
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: 587,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
})
await transporter.sendMail({
from: process.env.SMTP_USER,
to: 'you@yourcompany.com',
subject: 'New contact form submission: ' + body['full-name'],
text: body.message,
})
return { ok: true }
})
<form id="contact" onsubmit="event.preventDefault(); fetch('/api/contact', { method: 'POST', body: new FormData(event.target) })">
<input name="full-name" />
<input name="email" type="email" />
<textarea name="message"></textarea>
<button type="submit">Send</button>
</form>
This gives you full control: the payload shape, the sending logic, retries, whatever custom validation you want. It also means you own an SMTP account, its deliverability, rate limiting against spam bots, and a place to look up a submission if someone says they never heard back — none of which nodemailer gives you out of the box.
<form action="https://app.formbridge.ai/api/forms/fb_8h2k9p" method="POST">
<input name="full-name" />
<input name="email" type="email" />
<textarea name="message"></textarea>
<button type="submit">Send</button>
</form>
No server/api file, no SMTP credentials in your .env, no library to keep updated. Submissions land in a searchable inbox, get spam-scored automatically, and can trigger an autoresponder — all configured in the FormBridge dashboard, not your codebase.
Neither approach is wrong. A self-built route makes sense if the form is one piece of a larger custom workflow — writing to your own database, triggering internal logic beyond email — or if you'd rather not depend on a third party for something this simple. FormBridge makes sense if you'd rather not be the one who gets paged when the SMTP password expires. The free plan covers 1,000 submissions a month, which is enough for most contact forms to test the tradeoff without spending anything.
For custom logic beyond email — writing to your own database, triggering other internal systems — yes, a server route gives you that control. For a straightforward 'email me this submission' form, the extra code doesn't buy you much.
Low-level control over the exact request and response cycle, plus a dependency on a third-party service's uptime — in exchange you don't manage SMTP credentials, spam filtering, or a submissions dashboard yourself.
No. The form's action attribute points directly at the FormBridge endpoint, so Nitro never sees the request — there's no server route to write or deploy.
One email when we publish something worth reading. No spam — appropriately enough, we'd know.