Lección 9 de 20 · Lectura y práctica
Práctica: Construye un formulario de contacto con validación
Concepto claveEn SvelteKit, los Server Actions son funciones que se ejecutan exclusivamente en el servidor, permitiendo manejar operaciones sensibles como validación de datos, acceso a bases de datos y envío de emails sin exponer.
Del concepto a la práctica
Taller de esta lección
El formulario de contacto permite practicar dos capas sin confundirlas. La interfaz puede avisar pronto de un correo con formato incompleto, pero la Server Action debe repetir la comprobación porque cualquier cliente puede enviar una solicitud manual. El mensaje guardado debe conservar la relación entre remitente y contenido.
Ejemplo resuelto
Usa el registro local {email: 'ana@ejemplo.test', message: 'Necesito ayuda'}. La acción acepta si el correo contiene un único @ con texto a ambos lados y el mensaje tiene al menos 10 caracteres. No se envía nada externo: solo se simula el almacenamiento.
La regla de un @ es solo didáctica: acepta algunos valores que no son correos válidos y no demuestra control del buzón. Usa el tipo string y límites de tamaño antes de guardar; en una aplicación real un validador mantenido y una verificación separada cubren requisitos adicionales. Aquí Necesito ayuda mide13 caracteres y Hola4; usa IDs m1,m2 diferentes si aceptas más de un mensaje. No actives envío real ni interpretes el ID como correo entregado.
Pruébalo
Comprueba primero campos vacíos en la interfaz.
Repite las reglas en la acción del servidor.
Guarda únicamente después de pasar ambas reglas.
Devuelve un identificador de mensaje para confirmar la operación.
Comprueba tu resultado
Error frecuente: validar solo con atributos del navegador; corrígelo repitiendo la validación en servidor.
Ejercicio: prueba el registro válido, anaejemplo.test y el mensaje Hola. Resultado esperado: solo el primero se guarda y recibe un identificador.

Mapa de prácticaEl servidor puede obtener datos y producir el HTML inicial. El navegador muestra el resultado y ejecuta las interacciones que necesitan estado local. Mantén las claves sensibles en el servidor y define qué parte se ejecuta en cada entorno.
Ver la infografía en tamaño completo ↗Concepto clave
En SvelteKit, los Server Actions son funciones que se ejecutan exclusivamente en el servidor, permitiendo manejar operaciones sensibles como validación de datos, acceso a bases de datos y envío de emails sin exponer lógica al cliente. Imagina un restaurante donde el cliente solo ve el menú y hace su pedido (frontend), pero toda la preparación, cocción y empaquetado ocurre en la cocina (backend). Los Server Actions son como esos procesos de cocina: seguros, eficientes y ocultos al cliente.
La validación en este contexto va más allá de simples comprobaciones en el navegador. Implementamos una validación en dos capas: primero en el cliente para experiencia de usuario (feedback inmediato) y luego en el servidor para seguridad (validación definitiva). Esto es crucial porque el usuario podría deshabilitar JavaScript o manipular las validaciones del cliente.
Cómo funciona en la práctica
Vamos a construir un formulario de contacto completo paso a paso. Primero, creamos la estructura básica del formulario en Svelte con campos para nombre, email y mensaje. Luego, implementamos validación del lado del cliente usando las capacidades nativas de HTML5 y algo de JavaScript para feedback visual.
El siguiente paso es crear la Server Action en +page.server.js. Esta función recibirá los datos del formulario, realizará validación exhaustiva (incluyendo sanitización) y luego procesará la lógica de negocio. Finalmente, conectamos el formulario del cliente con la Server Action usando el atributo action de SvelteKit, que maneja automáticamente el envío y la respuesta.
Código en acción
Primero, el formulario básico en +page.svelte:
<form method="POST" action="?/sendContact">
<div>
<label for="name">Nombre completo</label>
<input
type="text"
id="name"
name="name"
required
minlength="2"
maxlength="100"
>
<span class="error">{@errors.name}</span>
</div>
<div>
<label for="email">Email</label>
<input
type="email"
id="email"
name="email"
required
>
<span class="error">{@errors.email}</span>
</div>
<div>
<label for="message">Mensaje</label>
<textarea
id="message"
name="message"
required
minlength="10"
maxlength="1000"
></textarea>
<span class="error">{@errors.message}</span>
</div>
<button type="submit">Enviar mensaje</button>
</form>Ahora, la Server Action en +page.server.js:
import { fail } from '@sveltejs/kit';
import { z } from 'zod';
export const actions = {
sendContact: async ({ request }) => {
const formData = await request.formData();
// Esquema de validación con Zod
const contactSchema = z.object({
name: z.string()
.min(2, 'El nombre debe tener al menos 2 caracteres')
.max(100, 'El nombre no puede exceder 100 caracteres')
.trim(),
email: z.string()
.email('Email inválido')
.max(150, 'Email demasiado largo'),
message: z.string()
.min(10, 'El mensaje debe tener al menos 10 caracteres')
.max(1000, 'El mensaje no puede exceder 1000 caracteres')
.trim()
});
try {
const validatedData = contactSchema.parse({
name: formData.get('name'),
email: formData.get('email'),
message: formData.get('message')
});
// Aquí iría la lógica de negocio real
// Ejemplo: await sendEmail(validatedData);
// Ejemplo: await saveToDatabase(validatedData);
console.log('Datos validados:', validatedData);
return { success: true, message: 'Mensaje enviado correctamente' };
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.flatten().fieldErrors;
return fail(400, {
errors: {
name: errors.name?.[0] || '',
email: errors.email?.[0] || '',
message: errors.message?.[0] || ''
}
});
}
return fail(500, {
errors: { general: 'Error interno del servidor' }
});
}
}
};Errores comunes
- Confiar solo en validación del cliente: Los usuarios pueden deshabilitar JavaScript o manipular las validaciones. Siempre valida en el servidor.
- No sanitizar los datos: Usar
.trim()en strings evita espacios innecesarios y potenciales problemas de almacenamiento. - Manejo pobre de errores: No capturar excepciones en las Server Actions puede causar caídas silenciosas. Usa try-catch siempre.
- Exponer detalles de error al cliente: En producción, muestra mensajes genéricos como "Error al procesar" en lugar de detalles técnicos.
- Olvidar el atributo method="POST": Sin él, el formulario se envía por GET, exponiendo datos en la URL.
Checklist de dominio
- Creé un formulario con validación HTML5 básica (required, minlength, type="email")
- Implementé una Server Action que recibe y procesa datos del formulario
- Usé una librería de validación (Zod, Yup, o similar) para validación robusta en servidor
- Manejé errores de validación mostrando mensajes específicos por campo
- Saniticé los datos de entrada (trim, escape cuando sea necesario)
- Protegí la Server Action contra errores inesperados con try-catch
- Proveí feedback claro al usuario sobre el resultado del envío
Extiende el formulario de contacto con campo de teléfono y notificación por email
Objetivo: Ampliar el formulario de contacto para incluir un campo de teléfono opcional y simular el envío de un email de confirmación.
- Agrega el campo teléfono al formulario en
+page.svelte:- Campo opcional (no required)
- Validación HTML5: type="tel" y pattern para formato internacional
- Muestra un ejemplo de formato en placeholder
- Actualiza la Server Action en
+page.server.js:- Modifica el esquema Zod para incluir teléfono como campo opcional
- Agrega validación: máximo 20 caracteres, solo números, espacios y signos +-()
- Si hay teléfono, normalízalo (elimina espacios y caracteres especiales)
- Simula envío de email:
- Crea una función
simulateEmailSendque retorne una promesa - Simula un retraso de 1-2 segundos con
setTimeout - Llama esta función después de la validación exitosa
- Maneja posibles errores en el envío del email
- Crea una función
- Mejora la UI:
- Muestra un indicador de carga mientras se procesa el envío
- Agrega un mensaje de éxito/error más detallado
- Permite reenviar el formulario después de un error
Pistas
- Usa
z.string().optional()en Zod para campos no requeridos - Para el pattern del teléfono, considera
pattern="[+]?[0-9\s\-()]+" - Usa
form.processingen Svelte para mostrar indicador de carga
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con SvelteKit Full-Stack: Construye Aplicaciones Web Performantes con Server Actions
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.