Calculadora de retorno de inversión y contacto
Calculadora en el navegador que estima cuánto le cuesta a un negocio un proceso manual y compara pago único contra plan mensual, con explicación paso a paso y un formulario de contacto protegido.
El problema
Quien contrata un sitio o un sistema a la medida suele comparar precios sin saber cuánto le cuesta hoy no tenerlo: horas de trabajo manual y clientes que se pierden por responder tarde. Del lado de quien cotiza, el problema es parecido: se regala el trabajo y las horas de hosting, soporte y cambios extra no se cobran.
Quería una página que ayudara a decidir con números, que se entendiera sin ser contador y que dijera con claridad qué incluye cada opción.
La solución
Una página /roi donde el visitante elige un servicio, indica horas semanales, costo por hora, clientes perdidos y valor por cliente. La calculadora estima el costo mensual del problema y compara:
- Pago único: el precio de lista de una vez.
- Plan mensual: 30 % al inicio y 18 mensualidades; al terminar, el sitio pasa al cliente.
- Mantenimiento opcional: hosting, dominio y soporte, que se paga cada mes y no está en el precio del sitio.
Muestra tres escenarios (conservador, esperado y optimista), la tabla de lo que se paga a 12, 24 y 36 meses y una sección “Cómo se calculó” con cada cifra explicada. Desde ahí, un botón lleva al formulario de contacto con el servicio ya elegido.
Decisiones técnicas
- Cálculo en el navegador. Son operaciones simples y no hay datos que proteger, así que no hace falta una API: la página responde al instante y funciona sin servidor. Antes había pensado en una API con NestJS; la descarté porque agregaba infraestructura sin aportar nada al usuario.
- Una función pura y probada. Toda la lógica vive en
utils/roi.ts, sin tocar el DOM, y se prueba con Vitest. Así, cambiar un precio o un porcentaje no rompe el resto sin que una prueba lo avise. - Supuestos a la vista. Los porcentajes de eficiencia y recuperación son estimaciones mías, no datos medidos. La página los muestra como supuestos y el resumen es cauteloso: si con el escenario conservador no se recupera la inversión, lo dice.
- Formulario con Pages Function.
functions/api/contacto.tsrevisa el origen, el tamaño, un campo trampa para bots, la validación compartida con el navegador y Cloudflare Turnstile; después envía un correo de texto plano con Resend. Los secretos viven en Cloudflare, no en el repositorio. - Validación en un solo lugar.
utils/contacto.tsse importa tanto en el navegador como en la función, para que las reglas no se desincronicen. - Eventos de medición sin datos personales. Solo se registra qué servicio se calculó y si se llegó a enviar el mensaje.
Lo que salió mal
- Mis propios números confundían. Con el ejemplo por defecto, el mantenimiento de $1,000 al mes se comía casi todo el beneficio conservador y la recuperación salía en 88 meses. No era un error de cálculo, pero una persona sin contexto lo leería como uno. La solución fue explicar cada paso y ajustar el texto del resumen.
- Turnstile en local. Fueron tres fallos seguidos: una clave secreta real con la clave pública de pruebas (
invalid-input-response), un widget sinlocalhosten sus dominios (error 110200) y un archivo.dev.varmal nombrado que Wrangler no leía. Desde entonces el README documenta el arreglo. pnpm devno ejecuta las Functions. El formulario daba 404 hasta que agregué el scriptpages:devy un aviso claro en modo desarrollo.- Un archivo de prueba dentro de
functions/se habría convertido en ruta. Todo lo que está ahí se publica, así que las pruebas viven entests/.
Qué mejoraría
- Medir con datos reales de clientes si los porcentajes de recuperación son razonables y ajustarlos.
- Publicar condiciones de servicio y de cancelación del plan mensual.
- Una imagen de vista previa propia al compartir
/roi. - Pruebas de extremo a extremo del formulario con un navegador automatizado, no solo de la función con
fetchsimulado.