Cuando empezamos a construir Kodeval, la primera pregunta técnica no fue qué framework usar. Fue si usar un framework. La respuesta, después de pensar un rato, fue no. Acá explicamos por qué.
El problema con los frameworks hoy
Los frameworks modernos como React, Vue o Svelte resuelven problemas reales: estado reactivo, composición de componentes, routing del lado del cliente. Pero cuando los mirás en contexto de un proyecto como Kodeval —un sitio estático con páginas mayormente de contenido y algo de interacción— el trade-off no cierra.
Un proyecto React típico arranca con un bundle de varios cientos de kilobytes antes de escribir una sola línea de código propio. Necesita un proceso de build, un entorno de Node, dependencias que se actualizan y rompen cosas, y un nivel de complejidad de tooling que no tiene razón de ser si tu sitio es esencialmente HTML con algo de JavaScript para interacción.
La complejidad debería ser proporcional al problema. Si el problema es simple, la solución debería serlo también.
Qué ganamos eligiendo vanilla
La ganancia más inmediata fue la velocidad. Sin proceso de build, sin bundler, sin tiempo de compilación. Un cambio en el HTML se ve al refrescar el navegador. En proyectos donde la iteración de diseño es frecuente, eso es un multiplicador real de productividad.
La segunda ganancia fue la durabilidad. HTML y CSS de 2015 sigue funcionando en 2026 sin tocar nada. No existe ese problema con React 16 cuando hoy estás en React 19. El HTML que escribimos hoy va a funcionar en 10 años sin que nadie tenga que hacer una migración.
Y la tercera, la que más importa para Kodeval Pages, fue la pedagógica: si tu producto es una librería de componentes que cualquiera puede copiar y pegar, ese código tiene que ser legible para cualquier desarrollador, independientemente de qué stack usa. Vanilla es el único lenguaje común.
Qué sacrificamos
No todo es positivo. El manejo de estado compartido es engorroso sin una librería. Para Kodeval, lo resolvimos con patrones simples: el estado de autenticación vive en auth.js y los componentes compartidos se inyectan en el DOM desde components.js. No es tan elegante como Context de React, pero funciona para nuestra escala.
Los componentes tampoco son reutilizables de la misma forma. En la práctica, duplicamos algunos bloques de CSS entre páginas. Lo mitigamos con variables CSS en :root y hojas de estilo compartidas, pero hay repetición que en un sistema de componentes no existiría.
- Sin hot reload real (solo recarga manual del navegador)
- Sin TypeScript nativo (errores de tipo en runtime, no en compilación)
- Sin tree-shaking (CSS sin usar se envía al cliente)
- El mantenimiento de los headers/footers requiere tocar el archivo JS manualmente
Cuándo tiene sentido hacer lo mismo
Esta decisión tiene sentido si tu proyecto cumple estas condiciones: el contenido es mayormente estático, la interactividad es limitada y conocida de antemano, la audiencia incluye desarrolladores que necesitan leer el código, y el equipo es pequeño y valora la simplicidad operativa.
Si estás construyendo una aplicación con estado complejo, muchas rutas dinámicas o un equipo grande que necesita tipado estricto, un framework probablemente sea la elección correcta. No hay respuesta universal.
Lo que hubiramos hecho diferente
La única cosa que cambiaríamos es haber definido antes los tokens de diseño. Empezamos con variables CSS sueltas en cada página y recien después las centralizamos en base.css. Hubiese sido mejor tenerlo claro desde el primer día, aunque sea con un sistema mínimo de colores y espaciado.
En retrospectiva, la apuesta por vanilla fue correcta para Kodeval. El sitio es rápido, el código es legible y el costo de mantenimiento es bajo. Cuando algo no funciona, la causa suele ser obvia. No hay magia negra del compilador ni abstracciones que oculten el problema.
A veces la mejor herramienta es la que ya venía con el navegador.