La salida estática sigue siendo posible
Una ruta Nitro impide que baste nuxt generate. Un formulario externo mantiene la opción de publicar todo como archivos.
integraciones · framework
server/api/ con Nitro facilita recibir, hasta que nuxt generate lo convierte en estático: no hay entorno donde ejecutar server/api/contact.post.ts.
Si elegiste Nuxt para exportar estático, usa un endpoint. Funciona igual con nuxt build en Node, nuxt generate en CDN y cualquier preset futuro.
configuración recomendada
Añade este HTML a tu sitio o utiliza el generador de formularios. Sustituye el enlace por el de tu formulario. El script alojado inserta la comprobación oculta, gestiona el envío y la verificación automática y conserva el borrador si hay errores. Tú controlas el HTML y el CSS. Los formularios Free muestran un enlace visible «Processed by mailcontact.app»; Pro y Plus no. Los avisos siguen el idioma del navegador; configura data-mailcontact-language="fr" en el formulario para forzar el francés.
<form action="https://mailcontact.app/api/forms/your-form-id" method="POST" data-mailcontact-form lang="es" data-mailcontact-language="es">
<input type="hidden" name="_language" value="es" />
<fieldset>
<legend>Contáctanos</legend>
<label>
Nombre (opcional)
<input name="name" type="text" autocomplete="name" maxlength="200" />
</label>
<label>
Correo electrónico
<input name="email" type="email" autocomplete="email" maxlength="320" required />
</label>
<label>
Mensaje
<textarea name="message" rows="5" maxlength="5000" required></textarea>
</label>
<noscript>
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden;">
<label>Sitio web
<input name="company_website" type="text" tabindex="-1" autocomplete="off" />
</label>
</div>
</noscript>
<button type="submit">Enviar mensaje</button>
</fieldset>
<p data-contact-status role="status" aria-live="polite" aria-atomic="true"></p>
</form>
<script defer src="https://mailcontact.app/forms/v1.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>Para un componente con su propio controlador de envío, carga el mismo script y utiliza MailContact.prepare(form) y MailContact.send() en lugar del marcador automático. Consulta la referencia de interfaces personalizadas para carga, avisos y atribución de Free.
el código
Este ejemplo envía directamente a la API. Mantén el campo obligatorio company_website presente y vacío. Los envíos nativos abren JSON si tienen éxito o una página de verificación si hace falta. Los scripts sin verificación envían los mensajes sospechosos a Spam; el spam claro también se retiene sin alertas ni consumo de cuota. Una respuesta de éxito confirma recepción, incluida revisión, o el descarte silencioso de una trampa rellenada. Consulta protección contra spam para conocer todo el funcionamiento.
<script setup>
// No server/api/contact.post.ts. Nothing here needs Nitro at runtime,
// so `nuxt generate` keeps this page fully working.
const sent = ref(false);
async function submit(event) {
await $fetch("https://mailcontact.app/api/forms/your-form-id", {
method: "POST",
body: new FormData(event.target),
});
sent.value = true;
}
</script>
<template>
<p v-if="sent">Thanks. We'll be in touch.</p>
<form v-else @submit.prevent="submit">
<input name="name" placeholder="Your name" required />
<input name="email" type="email" placeholder="[email protected]" required />
<textarea name="message" placeholder="What's on your mind?" required />
<input name="company_website" type="text" tabindex="-1" autocomplete="off"
style="position:absolute;left:-10000px" aria-hidden="true" />
<button>Send</button>
</form>
</template>cómo funciona
Una bandeja por proyecto con endpoint y email activos antes de añadir la página.
Pega en pages/contact.vue y sustituye ID. Sin server/, runtimeConfig ni claves privadas en el cliente.
Añade Discord, Slack, email o webhook y recibe avisos al instante.
por qué mailcontact
Una ruta Nitro impide que baste nuxt generate. Un formulario externo mantiene la opción de publicar todo como archivos.
La versión propia exige clave de email, almacenamiento y ajustes por proveedor. Aquí no hay clave que filtrar o renovar.
Los presets Nitro cambian por alojamiento. Una URL externa funciona igual sin tocarlos.
preguntas frecuentes
Sí, si despliegas servidor. server/api/contact.post.ts funciona con nuxt build en Node o serverless. Deja de funcionar con nuxt generate, sin Nitro para recibir. Si quieres estático, mantén fuera el formulario.
Sí. ref, $fetch y @submit.prevent son estables en ambas versiones. Puedes sustituir $fetch por fetch: envías FormData y no dependes de la capa de Nuxt.
No. useFetch sirve para datos durante el renderizado y deduplica y almacena en caché, algo inadecuado para un POST de un clic. Llama directamente a $fetch o fetch en el controlador.
company_website debe existir y estar vacío. Rellenarlo descarta sin avisar, pero un bot puede omitirlo. MailContact añade límites y controles de contenido y campañas. El script verifica automáticamente si hace falta; el spam claro se retiene sin alertas ni cuota.
relacionado
Formularios y una dirección de email real, juntos, con avisos en tus herramientas. Empieza con una cuenta gratuita.
Crear formulario gratisSin tarjeta de crédito. Free incluye un proyecto y 50 mensajes de formulario al mes.