Llevas horas perfeccionando tu portafolio en GitHub Pages. El diseño quedó limpio, la tipografía es impecable y la sección de contacto se ve profesional. Pero cuando alguien llena el formulario y hace clic en «Enviar»… nada. Una página en blanco, un error 405, o simplemente el formulario se recarga sin hacer absolutamente nada. Si esto te pasó, el problema no está en tu código HTML. Está en cómo funciona GitHub Pages por dentro.
Por qué GitHub Pages no puede procesar formularios por sí solo
GitHub Pages es un servicio de alojamiento estático. Esto significa que sirve archivos tal como están: HTML, CSS, JavaScript, imágenes. Lo que no puede hacer es ejecutar código del lado del servidor, es decir, PHP, Python, Node.js o cualquier lenguaje que procese datos de forma dinámica.
Un formulario de contacto tradicional necesita un servidor que reciba los datos, los lea y los envíe como correo electrónico. GitHub Pages simplemente no tiene ese servidor. No es un bug ni una limitación que vayan a corregir: es parte de su diseño. Es gratuito precisamente porque no ejecuta código del lado del servidor.
No es que tu formulario esté mal escrito. Es que GitHub Pages físicamente no puede hacer lo que le estás pidiendo. La solución está fuera de GitHub Pages, no dentro.
Por eso el clásico consejo de «agrega un archivo PHP» no funciona aquí. Aunque subas el archivo, GitHub Pages lo descarga como texto plano, no lo ejecuta. El resultado es el mismo: nada llega a tu correo.
La solución correcta: delegar el procesamiento a un servicio externo
La manera de resolver esto es usar un servicio de terceros que actúe como ese «servidor» que GitHub Pages no tiene. Tu formulario sigue siendo 100% HTML en tu repositorio, pero en lugar de enviar los datos a un script PHP tuyo, los envía a un endpoint externo. Si quieres entender esta solución a fondo y ver cómo aplica a distintas plataformas, consulta nuestra guía completa sobre formulario de contacto sin servidor.
El servicio más utilizado para esto es Formspree. Es gratuito para la mayoría de casos de uso, no requiere configurar nada en el servidor y funciona perfectamente con sitios alojados en GitHub Pages. Miles de desarrolladores lo usan exactamente para este propósito.
Guía completa: formulario de contacto funcional en GitHub Pages paso a paso
Vamos a configurar esto desde cero. El proceso completo toma menos de 15 minutos aunque sea la primera vez que lo haces.
Lo que necesitas antes de empezar
- Tu sitio ya publicado en GitHub Pages (o en proceso de publicarse)
- Un formulario HTML en tu código, aunque todavía no funcione
- Una cuenta de correo electrónico donde quieres recibir los mensajes
- 15 minutos de tiempo
Paso 1 — Crea tu cuenta gratuita en Formspree
Ve a formspree.io y regístrate con tu correo electrónico. El proceso es estándar: correo, contraseña, verificación. El plan gratuito te da 50 envíos de formulario por mes, que es más que suficiente para un portafolio personal o un proyecto de clase.
Paso 2 — Crea un formulario en el panel de Formspree
Una vez dentro de tu cuenta, haz clic en «+ New Form». Dale un nombre descriptivo, por ejemplo «Contacto portafolio GitHub». Formspree genera automáticamente un endpoint único para ese formulario. Tiene este formato:
https://formspree.io/f/xyzabc12
Ese código al final es tuyo y es único. Cópialo porque lo vas a usar en el siguiente paso. Ese endpoint es la «dirección postal» a la que tu formulario va a enviar los datos.
Paso 3 — Modifica el HTML de tu formulario
Abre el archivo HTML de tu sitio en GitHub donde está tu formulario. Busca la etiqueta <form> y cambia (o agrega) el atributo action para que apunte a tu endpoint de Formspree. También asegúrate de que tenga method="POST".
Así debería verse tu formulario completo:
<form action="https://formspree.io/f/xyzabc12" method="POST">
<label for="nombre">Tu nombre</label>
<input type="text" id="nombre" name="nombre" placeholder="Ej: María García" required>
<label for="email">Tu correo electrónico</label>
<input type="email" id="email" name="email" placeholder="Ej: [email protected]" required>
<label for="asunto">Asunto</label>
<input type="text" id="asunto" name="asunto" placeholder="¿En qué puedo ayudarte?" required>
<label for="mensaje">Mensaje</label>
<textarea id="mensaje" name="mensaje" rows="5" placeholder="Escribe tu mensaje aquí..." required></textarea>
<button type="submit">Enviar mensaje</button>
</form>
Reemplaza xyzabc12 con el código real de tu endpoint de Formspree. Eso es todo el cambio de código que necesitas hacer.
Paso 4 — Sube los cambios a tu repositorio de GitHub
Guarda el archivo HTML modificado y súbelo a tu repositorio como lo haces normalmente. Puedes hacerlo desde la interfaz web de GitHub (editando el archivo directamente) o desde tu terminal con los comandos habituales:
git add .
git commit -m "Agregar formulario de contacto funcional con Formspree"
git push origin main
GitHub Pages puede tardar entre 30 segundos y 2 minutos en reflejar los cambios. Es normal, no te preocupes si no aparece de inmediato.
Paso 5 — Haz una prueba real del formulario
Una vez que los cambios estén publicados, visita tu sitio en GitHub Pages, llena el formulario con datos reales (puedes usar los tuyos) y envíalo.
La primera vez que lo envíes, Formspree te mandará un correo de verificación pidiendo que confirmes que eres el dueño de esa dirección de email. Es un paso de seguridad de un solo clic. Revisa también tu carpeta de spam si no lo ves en los primeros dos minutos.
Después de confirmar, todos los mensajes futuros llegarán directamente a tu bandeja de entrada sin ningún paso adicional.
Cómo mejorar la experiencia después del envío
Por defecto, después de enviar el formulario Formspree muestra una página genérica de confirmación en sus servidores. Esto funciona, pero no es ideal si quieres mantener al visitante dentro de tu sitio. Hay dos formas de mejorarlo.
Opción A — Redirigir a tu propia página de agradecimiento
Crea una página gracias.html en tu repositorio con el mensaje que quieras mostrar. Luego agrega este campo oculto dentro de tu formulario:
<input type="hidden" name="_next" value="https://tuusuario.github.io/tu-repositorio/gracias.html">
Reemplaza la URL con la dirección real de tu página de agradecimiento en GitHub Pages. Después del envío, el visitante llegará a esa página en lugar de a la página genérica de Formspree.
Opción B — Mostrar un mensaje de éxito en la misma página con JavaScript
Si prefieres que no haya ninguna redirección y el mensaje de confirmación aparezca directamente en tu página sin recargarla, puedes manejar el envío con JavaScript usando la API de Formspree. El formulario envía los datos de forma asíncrona y tú controlas completamente lo que se muestra al usuario:
<form id="mi-formulario">
<input type="text" name="nombre" required placeholder="Tu nombre">
<input type="email" name="email" required placeholder="Tu correo">
<textarea name="mensaje" required placeholder="Tu mensaje"></textarea>
<button type="submit">Enviar</button>
</form>
<div id="mensaje-exito" style="display:none;">
¡Gracias! Tu mensaje llegó correctamente. Te responderé pronto.
</div>
<script>
const formulario = document.getElementById('mi-formulario');
formulario.addEventListener('submit', async function(e) {
e.preventDefault();
const datos = new FormData(formulario);
const respuesta = await fetch('https://formspree.io/f/xyzabc12', {
method: 'POST',
body: datos,
headers: { 'Accept': 'application/json' }
});
if (respuesta.ok) {
formulario.style.display = 'none';
document.getElementById('mensaje-exito').style.display = 'block';
}
});
</script>
Esta opción da la experiencia más pulida: el formulario desaparece y aparece el mensaje de confirmación, todo sin salir de la página. Es especialmente recomendable para portafolios donde la experiencia visual importa.
Cómo evitar el spam en tu formulario de GitHub Pages
Un formulario público en internet tarde o temprano atrae bots que lo llenan con mensajes basura. Formspree tiene filtros anti-spam activados por defecto, pero puedes reforzarlos con dos técnicas adicionales:
Técnica 1 — Campo honeypot (trampa para bots)
Agrega un campo de texto oculto para los humanos pero visible para los bots. Si un bot llena ese campo (lo hará porque lo ve en el código), Formspree descarta automáticamente ese envío. Los usuarios reales nunca lo ven ni lo llenan porque está oculto con CSS:
<!-- Campo honeypot: invisible para personas, visible para bots -->
<input type="text" name="_gotcha" style="display:none">
Técnica 2 — reCAPTCHA de Google
Para casos donde el spam es más intenso, Formspree tiene integración con reCAPTCHA de Google. Se activa desde el panel de configuración de tu formulario en Formspree, sin tocar código HTML adicional.
Errores frecuentes al configurar el formulario en GitHub Pages
Error: el formulario redirige a una página de Formspree en inglés después de enviarse
Es el comportamiento por defecto si no configuras una página propia de agradecimiento. No es un error de funcionamiento: el mensaje sí llegó a tu correo. Para cambiar esto, agrega el campo oculto _next que se explicó en la sección anterior.
Error: el primer envío no llega al correo
Formspree manda un correo de verificación antes de procesar el primer envío real. Revisa tu bandeja de entrada y también la carpeta de spam. Si no confirmas ese correo, los mensajes no llegarán.
Error: la página dice «Method Not Allowed» o error 405
Esto pasa cuando la etiqueta <form> no tiene el atributo method="POST". Sin ese atributo, el navegador usa GET por defecto, que Formspree no acepta para el envío de formularios. Asegúrate de que tu etiqueta de apertura se vea así: <form action="https://formspree.io/f/tucodigo" method="POST">.
Error: el correo llega pero los campos aparecen vacíos o sin etiquetar
Cada campo del formulario (input, textarea, select) necesita el atributo name. Sin él, Formspree no puede identificar qué dato pertenece a qué campo. Verifica que todos tus campos tengan algo como name="nombre", name="email", name="mensaje", etc.
Error: el formulario funciona en local pero no en GitHub Pages
Esto puede pasar si estás probando el archivo HTML abriéndolo directamente desde tu computadora (con una URL que empieza por file://). Algunos navegadores bloquean peticiones externas desde archivos locales por razones de seguridad. Siempre prueba el formulario desde la URL pública de GitHub Pages, no desde el archivo local.
Preguntas frecuentes sobre formularios de contacto en GitHub Pages
¿Puedo recibir archivos adjuntos a través del formulario?
El plan gratuito de Formspree no incluye manejo de archivos adjuntos. Si necesitas que los usuarios puedan subir archivos (como un CV o portafolio en PDF), necesitarías el plan de pago de Formspree o una solución alternativa como Cloudinary combinado con Formspree para el texto.
¿Funciona si mi repositorio de GitHub Pages es privado?
Sí. El formulario funciona desde el sitio publicado, no desde el repositorio. Aunque el repositorio sea privado, el sitio publicado en tuusuario.github.io es público y el formulario funciona exactamente igual.
¿Puedo tener varios formularios en el mismo sitio?
Sí, pero en el plan gratuito de Formspree solo puedes tener un formulario activo. Si necesitas dos formularios diferentes (por ejemplo, uno de contacto y uno de suscripción), necesitarías el plan de pago o usar dos cuentas distintas.
¿Es posible que GitHub Pages nunca pueda procesar formularios por sí solo?
Es posible que en el futuro GitHub integre alguna forma de funciones del lado del servidor, pero hoy por hoy no existe esa funcionalidad. Netlify, por ejemplo, sí ofrece Netlify Functions como solución propia para este problema. Pero para GitHub Pages, la solución correcta hoy es usar un servicio externo como Formspree.
¿Necesito conocer Git para hacer estos cambios?
No necesariamente. GitHub tiene un editor de archivos directamente en el navegador. Puedes ir a tu repositorio, hacer clic en el archivo HTML, clic en el ícono de lápiz para editar, hacer el cambio en el atributo action del formulario y hacer commit directamente desde la interfaz web. Sin tocar la terminal.
Resumen: tu formulario de GitHub Pages en tres ideas clave
Primero, el problema no es tu código: GitHub Pages es un hosting estático que no puede ejecutar PHP ni ningún lenguaje de servidor, así que los formularios HTML tradicionales simplemente no funcionan ahí.
Segundo, la solución es delegar el procesamiento a un servicio externo: cambias una sola línea de HTML (el atributo action de tu formulario) para apuntar al endpoint de Formspree, y ese servicio se encarga del resto.
Tercero, el proceso completo toma menos de 15 minutos, no requiere saber programación de backend, no cuesta nada en proyectos pequeños y funciona de forma confiable desde el primer día.
Si tu portafolio o proyecto en GitHub Pages ya tiene un formulario que no funcionaba, con los cambios de esta guía debería estar recibiendo mensajes reales en tu correo hoy mismo. ¿Tienes alguna duda sobre un paso específico o sobre cómo adaptar esto a tu sitio en particular? Déjanos un comentario y te ayudamos.

