Blog

Nuxt Contact Form: Server Routes vs. a Hosted Form Backend

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.

← Back to the blog
AI Powered

Explore this article with AI

Get an instant summary, key takeaways, action items, and answers to your questions about this article.

Choose your AI assistant
ChatGPT Perplexity
Quick answer

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.

Two ways to handle a Nuxt contact form

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.

Option A: a server route + email library

// 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.

Option B: point the form at FormBridge

<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.

The honest tradeoff

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.

Frequently asked

Is a Nuxt server route more powerful than a hosted form backend?

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.

What do you give up by using a hosted form backend instead of your own route?

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.

Do I still need server/api/contact.post.ts if I use FormBridge?

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.

Key facts

  • Nuxt's Nitro server engine lets you define API routes under server/api/, e.g. server/api/contact.post.ts for a POST handler.
  • A self-hosted email route requires managing SMTP credentials, sender deliverability, and spam mitigation independently of the framework.
  • Pointing a form's action attribute directly at an external endpoint bypasses the Nuxt server runtime entirely — no server/api route is invoked.

Terms in this post

Nitro
The server engine underlying Nuxt 3, which powers server routes defined under the server/api/ directory and can be deployed to various runtimes (Node, edge, serverless).

Get the next one in your inbox.

One email when we publish something worth reading. No spam — appropriately enough, we'd know.