Integration guide · Nuxt
A Nuxt contact form that emails you — with or without a server route
A contact form in Nuxt doesn't need its own Nitro server route, database, or email setup. Point a plain HTML form at a PostTo endpoint and you're done — it works in any page with zero client-side JavaScript.
Want more? Add a server route that forwards submissions through PostTo's HMAC-signed API: the signing secret stays in a runtime config value, and every request is protected against replay and forgery.
Free plan, no credit card required.
Three steps, a few minutes
Create an endpoint
Sign up free, create an endpoint in the dashboard, and set your destination email. You'll get an endpoint URL right away — and a signing secret if you enable signed mode.
Pick your integration
Simplest: a plain HTML form in any page. More control: a Nitro server route that signs the request server-side and lets you render inline success states.
Deploy anywhere
Node, Vercel, Netlify, a static host — PostTo is a plain HTTPS endpoint, so nothing about your Nuxt deployment target changes.
The code
Replace YOUR_TOKEN
with the endpoint URL from your dashboard.
<template>
<form action="https://postto.dev/api/v1/send/YOUR_TOKEN" method="POST">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email" required>
<textarea name="message" required></textarea>
<!-- Honeypot: bots fill this in, humans never see it -->
<input type="text" name="_hp" tabindex="-1" autocomplete="off" style="display:none">
<!-- Where to send the visitor after a successful submission -->
<input type="hidden" name="_next" value="https://yoursite.com/thanks">
<button type="submit">Send</button>
</form>
</template>
import crypto from 'node:crypto';
export default defineEventHandler(async (event) => {
const payload = await readBody(event);
const { posttoSecret } = useRuntimeConfig();
const ts = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify(payload);
const sig = crypto
.createHmac('sha256', posttoSecret)
.update(`${ts}.${body}`)
.digest('hex');
return await $fetch('https://postto.dev/api/v1/send/YOUR_TOKEN', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-PostTo-Timestamp': ts,
'X-PostTo-Signature': sig,
},
body, // exact bytes that were signed
});
});
Good to know
The plain form needs no client JS
The first snippet is static markup with no script block — no fetch, no submit handler. The browser posts directly to PostTo and follows the redirect to your thanks page.
Keep the secret out of the browser
Signed mode requires your endpoint's secret key, so it belongs in runtimeConfig (not runtimeConfig.public), which Nuxt keeps server-only and out of the client bundle.
Spam protection is already wired in
The hidden _hp field is a honeypot — humans never see it, bots fill it in, and PostTo silently discards those submissions. Server-side baseline filtering (heuristics and optional AI classification) runs on every submission after that, so you don't need a CAPTCHA to start.
From the docs
Frequently asked questions
- Does this work with Nuxt static generation (nuxi generate)?
- The plain HTML form does — it's just markup, so it survives static generation unchanged. The signed server route needs a Node runtime, so use it on deployments that support Nitro server routes.
- When should I use signed mode instead of the plain form?
- Use the plain form for public contact forms — the endpoint token plus baseline spam filtering is the right level of protection. Use signed mode when submissions come from your own server route and you want cryptographic proof they weren't forged or replayed.
- Can I show an inline success message instead of redirecting?
- Yes. Submit the form with $fetch (or your server route) and an Accept: application/json header, and render the JSON response — a small script block with a submit handler is all it takes.
- What does it cost?
- The free plan includes 50 submissions per month with the full dashboard — no credit card required. Paid plans start at $9/month.
Add a form to your Nuxt site today
Create an endpoint, paste the snippet, and see your first submission in the dashboard — all on the free plan.
Try PostTo free